Skip to content

Commit 43b0d64

Browse files
committed
Update README.md
1 parent 2921ed5 commit 43b0d64

File tree

1 file changed

+137
-137
lines changed

1 file changed

+137
-137
lines changed

PushToSLPhoneApp/README.md

+137-137
Original file line numberDiff line numberDiff line change
@@ -39,146 +39,146 @@ Here are couple of links to provide guidance (from Windows Dev Center) -
3939

4040
9. Make sure you are calling the following method at the app startup. Configure your *Notification Hub name* and the *DefaultListenSharedAccessSignature*.
4141

42-
public async void RegisterToReceiveNotifications()
43-
{
44-
string notificationHubName = "[hubName]";
45-
string connectionString = "[ConnectionString-DefaultListenSharedAccessSignature]";
46-
47-
// Register with WNS
48-
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
49-
50-
// Register with Azure Notification Hubs
51-
NotificationHub hub = new NotificationHub(notificationHubName, connectionString);
52-
hub.Register(channel.Uri);
53-
Debug.WriteLine("ChannelURI : {0}", channel.Uri);
54-
}
42+
public async void RegisterToReceiveNotifications()
43+
{
44+
string notificationHubName = "[hubName]";
45+
string connectionString = "[ConnectionString-DefaultListenSharedAccessSignature]";
46+
47+
// Register with WNS
48+
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
49+
50+
// Register with Azure Notification Hubs
51+
NotificationHub hub = new NotificationHub(notificationHubName, connectionString);
52+
hub.Register(channel.Uri);
53+
Debug.WriteLine("ChannelURI : {0}", channel.Uri);
54+
}
5555

5656
10. Add a Notification Hub class which abstracts the functionality of registering with the Azure Notification Hubs. This is based on [Notification Hubs REST APIs]. See explanation in the following steps:
5757

58-
class NotificationHub
59-
{
60-
private const string ApiVersion = "?api-version=2014-09";
61-
private const string AuthHeader = "Authorization";
62-
private const string ContentType = "application/atom+xml;type=entry;charset=utf-8";
63-
64-
static string HubName { get; set; }
65-
static string ConnectionString { get; set; }
66-
static string Endpoint { get; set; }
67-
static string SasKeyName { get; set; }
68-
static string SasKeyValue { get; set; }
69-
static string Payload { get; set; }
70-
71-
public NotificationHub(string hubName, string connectionString)
72-
{
73-
HubName = hubName;
74-
ConnectionString = connectionString;
75-
}
76-
77-
public void Register(string pushChannel)
78-
{
79-
ParseConnectionInfo();
80-
SendNHRegistrationRequest(pushChannel);
81-
}
82-
83-
// From http://msdn.microsoft.com/en-us/library/dn495627.aspx
84-
private static void ParseConnectionInfo()
85-
{
86-
if (string.IsNullOrWhiteSpace(HubName))
87-
{
88-
throw new InvalidOperationException("Hub name is empty");
89-
}
90-
91-
var parts = ConnectionString.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
92-
93-
if (parts.Length != 3)
94-
{
95-
throw new InvalidOperationException("Error parsing connection string: " + ConnectionString);
96-
}
97-
98-
foreach (var part in parts)
99-
{
100-
if (part.StartsWith("Endpoint"))
101-
{
102-
Endpoint = "https" + part.Substring(11);
103-
}
104-
else if (part.StartsWith("SharedAccessKeyName"))
105-
{
106-
SasKeyName = part.Substring(20);
107-
}
108-
else if (part.StartsWith("SharedAccessKey"))
109-
{
110-
SasKeyValue = part.Substring(16);
111-
}
112-
}
113-
}
114-
private static string GenerateSaSToken(Uri uri)
115-
{
116-
var targetUri = WebUtility.UrlEncode(uri.ToString().ToLower()).ToLower();
117-
118-
var expiresOnDate = Convert.ToInt64(DateTime.UtcNow.Subtract
119-
(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds) + 60 * 60;
120-
var toSign = targetUri + "\n" + expiresOnDate;
121-
122-
var keyBytes = Encoding.UTF8.GetBytes(SasKeyValue);
123-
var mac = new HMACSHA256(keyBytes);
124-
mac.Initialize();
125-
var rawHmac = mac.ComputeHash(Encoding.UTF8.GetBytes(toSign));
126-
var signature = WebUtility.UrlEncode(Convert.ToBase64String(rawHmac));
127-
128-
var token = "SharedAccessSignature sr=" + targetUri + "&sig="
129-
+ signature + "&se=" + expiresOnDate + "&skn=" + SasKeyName;
130-
return token;
131-
}
132-
133-
private static void SendNHRegistrationRequest(string pushChannel)
134-
{
135-
Payload =
136-
@"<?xml version=""1.0"" encoding=""utf-8""?>
137-
<entry xmlns=""http://www.w3.org/2005/Atom"">
138-
<content type=""application/xml"">
139-
<WindowsRegistrationDescription xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"">
140-
<ChannelUri>{WindowsPushChannel}</ChannelUri>
141-
</WindowsRegistrationDescription >
142-
</content>
143-
</entry>";
144-
145-
Payload = Payload.Replace("{WindowsPushChannel}", pushChannel);
146-
147-
var uri = new Uri(Endpoint + HubName + "/registrations/" + ApiVersion);
148-
var sendRequest = WebRequest.CreateHttp(uri);
149-
sendRequest.Method = "POST";
150-
sendRequest.ContentType = ContentType;
151-
sendRequest.Headers[AuthHeader] = GenerateSaSToken(uri);
152-
sendRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), sendRequest);
153-
}
154-
155-
static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
156-
{
157-
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
158-
// End the stream request operation
159-
Stream postStream = request.EndGetRequestStream(asynchronousResult);
160-
161-
byte[] byteArray = Encoding.UTF8.GetBytes(Payload);
162-
163-
postStream.Write(byteArray, 0, byteArray.Length);
164-
postStream.Close();
165-
166-
//Start the web request
167-
request.BeginGetResponse(new AsyncCallback(GetResponceStreamCallback), request);
168-
}
169-
170-
static void GetResponceStreamCallback(IAsyncResult callbackResult)
171-
{
172-
HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
173-
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
174-
using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
175-
{
176-
string result = httpWebStreamReader.ReadToEnd();
177-
//For debug: show results
178-
Debug.WriteLine(result);
179-
}
180-
}
181-
}
58+
class NotificationHub
59+
{
60+
private const string ApiVersion = "?api-version=2014-09";
61+
private const string AuthHeader = "Authorization";
62+
private const string ContentType = "application/atom+xml;type=entry;charset=utf-8";
63+
64+
static string HubName { get; set; }
65+
static string ConnectionString { get; set; }
66+
static string Endpoint { get; set; }
67+
static string SasKeyName { get; set; }
68+
static string SasKeyValue { get; set; }
69+
static string Payload { get; set; }
70+
71+
public NotificationHub(string hubName, string connectionString)
72+
{
73+
HubName = hubName;
74+
ConnectionString = connectionString;
75+
}
76+
77+
public void Register(string pushChannel)
78+
{
79+
ParseConnectionInfo();
80+
SendNHRegistrationRequest(pushChannel);
81+
}
82+
83+
// From http://msdn.microsoft.com/en-us/library/dn495627.aspx
84+
private static void ParseConnectionInfo()
85+
{
86+
if (string.IsNullOrWhiteSpace(HubName))
87+
{
88+
throw new InvalidOperationException("Hub name is empty");
89+
}
90+
91+
var parts = ConnectionString.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
92+
93+
if (parts.Length != 3)
94+
{
95+
throw new InvalidOperationException("Error parsing connection string: " + ConnectionString);
96+
}
97+
98+
foreach (var part in parts)
99+
{
100+
if (part.StartsWith("Endpoint"))
101+
{
102+
Endpoint = "https" + part.Substring(11);
103+
}
104+
else if (part.StartsWith("SharedAccessKeyName"))
105+
{
106+
SasKeyName = part.Substring(20);
107+
}
108+
else if (part.StartsWith("SharedAccessKey"))
109+
{
110+
SasKeyValue = part.Substring(16);
111+
}
112+
}
113+
}
114+
private static string GenerateSaSToken(Uri uri)
115+
{
116+
var targetUri = WebUtility.UrlEncode(uri.ToString().ToLower()).ToLower();
117+
118+
var expiresOnDate = Convert.ToInt64(DateTime.UtcNow.Subtract
119+
(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds) + 60 * 60;
120+
var toSign = targetUri + "\n" + expiresOnDate;
121+
122+
var keyBytes = Encoding.UTF8.GetBytes(SasKeyValue);
123+
var mac = new HMACSHA256(keyBytes);
124+
mac.Initialize();
125+
var rawHmac = mac.ComputeHash(Encoding.UTF8.GetBytes(toSign));
126+
var signature = WebUtility.UrlEncode(Convert.ToBase64String(rawHmac));
127+
128+
var token = "SharedAccessSignature sr=" + targetUri + "&sig="
129+
+ signature + "&se=" + expiresOnDate + "&skn=" + SasKeyName;
130+
return token;
131+
}
132+
133+
private static void SendNHRegistrationRequest(string pushChannel)
134+
{
135+
Payload =
136+
@"<?xml version=""1.0"" encoding=""utf-8""?>
137+
<entry xmlns=""http://www.w3.org/2005/Atom"">
138+
<content type=""application/xml"">
139+
<WindowsRegistrationDescription xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"">
140+
<ChannelUri>{WindowsPushChannel}</ChannelUri>
141+
</WindowsRegistrationDescription >
142+
</content>
143+
</entry>";
144+
145+
Payload = Payload.Replace("{WindowsPushChannel}", pushChannel);
146+
147+
var uri = new Uri(Endpoint + HubName + "/registrations/" + ApiVersion);
148+
var sendRequest = WebRequest.CreateHttp(uri);
149+
sendRequest.Method = "POST";
150+
sendRequest.ContentType = ContentType;
151+
sendRequest.Headers[AuthHeader] = GenerateSaSToken(uri);
152+
sendRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), sendRequest);
153+
}
154+
155+
static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
156+
{
157+
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
158+
// End the stream request operation
159+
Stream postStream = request.EndGetRequestStream(asynchronousResult);
160+
161+
byte[] byteArray = Encoding.UTF8.GetBytes(Payload);
162+
163+
postStream.Write(byteArray, 0, byteArray.Length);
164+
postStream.Close();
165+
166+
//Start the web request
167+
request.BeginGetResponse(new AsyncCallback(GetResponceStreamCallback), request);
168+
}
169+
170+
static void GetResponceStreamCallback(IAsyncResult callbackResult)
171+
{
172+
HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
173+
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
174+
using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
175+
{
176+
string result = httpWebStreamReader.ReadToEnd();
177+
//For debug: show results
178+
Debug.WriteLine(result);
179+
}
180+
}
181+
}
182182

183183
11. `ParseConnectionInfo` & `GenerateSaSToken` are used to create the standard Authorization header you need to communicate with Azure Notification Hubs.
184184

0 commit comments

Comments
 (0)