如何将原始通知发送到 Azure 通知中心
How to send Raw notification to azure notification hub
我是 azure 的新手,我已经将我的应用程序配置为接收原始通知,并且我能够从 azure 网站的调试页面接收它们,我的问题是,如何从我的网站发送它们后端?我可以发送所有类型的通知,但无法弄清楚如何发送那种类型...一个非常简单的通知,如 azure 通知(Windows 一个不是 Windows phone一),只有一个未格式化的字符串
假设您使用的是 WNS(而不是 MPNS),您只需从 hub.wns object 调用 SendRaw。语法是:
sendRaw(tags, payload, optionsOrCallbackopt, callback)
在 http://dl.windowsazure.com/nodedocs/WnsService.html 的推送通知中心查看 WNS 服务的 NodeJS 文档。
对于 .NET 后端,您可以使用 NotificationHubClient.SendNotificationAsync,如 https://msdn.microsoft.com/en-us/library/azure/dn369343.aspx. The notification class you feed in will be a WindowsNotification as described at https://msdn.microsoft.com/en-us/library/azure/microsoft.servicebus.notifications.windowsnotification.aspx.
中所述
由于要发送原始通知,因此必须自己创建负载。有关如何创建原始负载的文档位于 https://msdn.microsoft.com/en-us/library/windows/apps/jj676791.aspx,更具体地说:
- HTTP Content-Type header 必须设置为 "application/octet-stream"。
- HTTP X-WNS-Type header 必须设置为 "wns/raw"。
- 通知 body 可以包含任何小于 5 KB 的字符串负载。
下面是一些可以执行此任务的工作代码(符合 .Net Standard 2.0):
public static async Task SendRawNotification(string notificationString)
{
var sasToken = CreateSASToken($"http://{NotificationNamespace}.servicebus.windows.net/{NotificationHub}", "DefaultFullSharedAccessSignature", $"{SharedAccessKey}");
var description = new NotificationDescription
{
NotificationType = type,
Notification = JsonConvert.SerializeObject(notification)
};
var serialized = JsonConvert.SerializeObject(description);
byte[] contentInBytes = Encoding.UTF8.GetBytes(serialized);
HttpWebRequest request = WebRequest.Create($"https://{NotificationNamespace}.servicebus.windows.net/{NotificationHub}/messages/?api-version=2015-01") as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/octet-stream";
request.Headers.Add("Authorization", sasToken);
request.Headers.Add("X-WNS-Type", "wns/raw");
request.Headers.Add("ServiceBusNotification-Format", "windows");
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
using (HttpWebResponse webResponse = await request.GetResponseAsync() as HttpWebResponse)
{
if (webResponse.StatusCode != HttpStatusCode.Created)
{
throw new InvalidOperationException($"Failed to create notification: {serialized}");
}
}
}
private static string CreateSASToken(string resourceUri, string keyName, string key)
{
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 3600); //EXPIRES in 1h
string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture,
"SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
return sasToken;
}
此问题的先前答案包含无效链接,未提供有关如何实现此功能的有用信息。
不幸的是,在撰写此回复时,Azure 通知中心 SDK 在使用 NuGet 包时发送原始通知方面出现问题:Microsoft.Azure.NotificationHubs (2.0.0)
此功能在 Microsoft.Azure.NotificationHubs (1.0.9) 中可用并且仍然有效,但是,此功能仅可用 in.Net 框架项目针对 4.6.1。
如果您希望在 .Net
核心或 .Net
标准 2.0 项目中发送原始通知,那么您将在发送时收到一个类似于 "You have to set the content type to 'application/octet-stream'" 的异常。这是因为,在 SDK 本身中,他们使用 StringContent object 构造 HttpRequest,它将 "charset-utf8" 附加到 ContentType header.
直到发布 NuGet 包的更新(Microsoft 已经意识到这个问题并且目前正在努力提供更新),然后您将必须自己创建 HttpRequest。
不幸的是,关于如何实现这一点的 Microsoft 文档再次严重缺乏细节。
完成此操作有几个步骤,如下所示:
- 创建您的资源 URI 字符串
您尝试使用的资源的 URI。为了向 Azure 通知中心发送请求,其格式应如下所示:
https://{NotificationHubNamespace}.servicebus.windows.net/{NotificationHubName}
因此,如果您的通知命名空间是 "notification-ns" 并且您的通知中心称为 "notification-hub",那么 URI 应该是:
https://notification-ns.servicebus.windows.net/notification-hub
- 从 Azure 门户保存您的 DefaultSharedAccessSignature
您需要从 Azure 门户复制您的 DefaultFullSharedAccessSignature。您的签名应如下所示:
Endpoint=sb://xxxx.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=xxxxxxxxx=
复制/保存 "SharedAccessKey=" 之后的部分,因为这用于生成访问令牌。
- 生成您的 SharedAccessSignature 令牌(SAS 密钥)
调用CreateSASToken函数,设置参数如下:
resourceUri:"https://{NotificationHubNamespace}.servicebus.windows.net/{NotificationHubName}"
keyName: "DefaultFullSharedAccessSignature"
key: the saved part following "SharedAccessKey=" in the DefaultFullSharedAccessSignature
这将生成格式正确的 SharedAccessSignature (SAS Key)
现在,您可以使用 System.Net.Http library
创建 HttpWebRequest
来发送原始通知。
一位微软工程师为我提供了以下示例程序,它也可以发送原始通知,我认为在这里分享它是合适的:
using Newtonsoft.Json.Linq;
using System;
using System.Globalization;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace ConsoleApp
{
class Program
{
static string NH_NAMESPACE = "{Please input}";
static string HUB_NAME = "{Please input}";
static string KEY_NAME = "DefaultFullSharedAccessSignature";
static string KEY_VALUE = "{Please input}";
static void Main(string[] args)
{
JObject jobject = new JObject();
jobject.Add("text1", "my app");
jobject.Add("text2", "my value");
SendNotificaitonAsync(jobject.ToString()).Wait();
Console.ReadLine();
}
private static async Task SendNotificaitonAsync(string content)
{
string resourceUri = $"https://{NH_NAMESPACE}.servicebus.windows.net/{HUB_NAME}/messages/";
using (var request = CreateHttpRequest(HttpMethod.Post, resourceUri))
{
request.Content = new StringContent(content, Encoding.UTF8, "application/octet-stream");
request.Content.Headers.ContentType.CharSet = string.Empty;
var httpClient = new HttpClient();
var response = await httpClient.SendAsync(request);
Console.WriteLine(response.StatusCode);
}
}
private static HttpRequestMessage CreateHttpRequest(HttpMethod method, String resourceUri)
{
var request = new HttpRequestMessage(method, $"{resourceUri}?api-version=2017-04");
request.Headers.Add("Authorization", createToken(resourceUri, KEY_NAME, KEY_VALUE));
request.Headers.Add("X-WNS-Type", "wns/raw");
request.Headers.Add("ServiceBusNotification-Format", "windows");
return request;
}
private static string createToken(string resourceUri, string keyName, string key)
{
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var week = 60 * 60 * 24 * 7;
var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + week);
string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
return sasToken;
}
}
}
我是 azure 的新手,我已经将我的应用程序配置为接收原始通知,并且我能够从 azure 网站的调试页面接收它们,我的问题是,如何从我的网站发送它们后端?我可以发送所有类型的通知,但无法弄清楚如何发送那种类型...一个非常简单的通知,如 azure 通知(Windows 一个不是 Windows phone一),只有一个未格式化的字符串
假设您使用的是 WNS(而不是 MPNS),您只需从 hub.wns object 调用 SendRaw。语法是:
sendRaw(tags, payload, optionsOrCallbackopt, callback)
在 http://dl.windowsazure.com/nodedocs/WnsService.html 的推送通知中心查看 WNS 服务的 NodeJS 文档。
对于 .NET 后端,您可以使用 NotificationHubClient.SendNotificationAsync,如 https://msdn.microsoft.com/en-us/library/azure/dn369343.aspx. The notification class you feed in will be a WindowsNotification as described at https://msdn.microsoft.com/en-us/library/azure/microsoft.servicebus.notifications.windowsnotification.aspx.
中所述由于要发送原始通知,因此必须自己创建负载。有关如何创建原始负载的文档位于 https://msdn.microsoft.com/en-us/library/windows/apps/jj676791.aspx,更具体地说:
- HTTP Content-Type header 必须设置为 "application/octet-stream"。
- HTTP X-WNS-Type header 必须设置为 "wns/raw"。
- 通知 body 可以包含任何小于 5 KB 的字符串负载。
下面是一些可以执行此任务的工作代码(符合 .Net Standard 2.0):
public static async Task SendRawNotification(string notificationString)
{
var sasToken = CreateSASToken($"http://{NotificationNamespace}.servicebus.windows.net/{NotificationHub}", "DefaultFullSharedAccessSignature", $"{SharedAccessKey}");
var description = new NotificationDescription
{
NotificationType = type,
Notification = JsonConvert.SerializeObject(notification)
};
var serialized = JsonConvert.SerializeObject(description);
byte[] contentInBytes = Encoding.UTF8.GetBytes(serialized);
HttpWebRequest request = WebRequest.Create($"https://{NotificationNamespace}.servicebus.windows.net/{NotificationHub}/messages/?api-version=2015-01") as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/octet-stream";
request.Headers.Add("Authorization", sasToken);
request.Headers.Add("X-WNS-Type", "wns/raw");
request.Headers.Add("ServiceBusNotification-Format", "windows");
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
using (HttpWebResponse webResponse = await request.GetResponseAsync() as HttpWebResponse)
{
if (webResponse.StatusCode != HttpStatusCode.Created)
{
throw new InvalidOperationException($"Failed to create notification: {serialized}");
}
}
}
private static string CreateSASToken(string resourceUri, string keyName, string key)
{
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 3600); //EXPIRES in 1h
string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture,
"SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
return sasToken;
}
此问题的先前答案包含无效链接,未提供有关如何实现此功能的有用信息。
不幸的是,在撰写此回复时,Azure 通知中心 SDK 在使用 NuGet 包时发送原始通知方面出现问题:Microsoft.Azure.NotificationHubs (2.0.0)
此功能在 Microsoft.Azure.NotificationHubs (1.0.9) 中可用并且仍然有效,但是,此功能仅可用 in.Net 框架项目针对 4.6.1。
如果您希望在 .Net
核心或 .Net
标准 2.0 项目中发送原始通知,那么您将在发送时收到一个类似于 "You have to set the content type to 'application/octet-stream'" 的异常。这是因为,在 SDK 本身中,他们使用 StringContent object 构造 HttpRequest,它将 "charset-utf8" 附加到 ContentType header.
直到发布 NuGet 包的更新(Microsoft 已经意识到这个问题并且目前正在努力提供更新),然后您将必须自己创建 HttpRequest。
不幸的是,关于如何实现这一点的 Microsoft 文档再次严重缺乏细节。
完成此操作有几个步骤,如下所示:
- 创建您的资源 URI 字符串
您尝试使用的资源的 URI。为了向 Azure 通知中心发送请求,其格式应如下所示:
https://{NotificationHubNamespace}.servicebus.windows.net/{NotificationHubName}
因此,如果您的通知命名空间是 "notification-ns" 并且您的通知中心称为 "notification-hub",那么 URI 应该是:
https://notification-ns.servicebus.windows.net/notification-hub
- 从 Azure 门户保存您的 DefaultSharedAccessSignature
您需要从 Azure 门户复制您的 DefaultFullSharedAccessSignature。您的签名应如下所示:
Endpoint=sb://xxxx.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=xxxxxxxxx=
复制/保存 "SharedAccessKey=" 之后的部分,因为这用于生成访问令牌。
- 生成您的 SharedAccessSignature 令牌(SAS 密钥)
调用CreateSASToken函数,设置参数如下:
resourceUri:"https://{NotificationHubNamespace}.servicebus.windows.net/{NotificationHubName}"
keyName: "DefaultFullSharedAccessSignature"
key: the saved part following "SharedAccessKey=" in the DefaultFullSharedAccessSignature
这将生成格式正确的 SharedAccessSignature (SAS Key)
现在,您可以使用 System.Net.Http library
创建 HttpWebRequest
来发送原始通知。
一位微软工程师为我提供了以下示例程序,它也可以发送原始通知,我认为在这里分享它是合适的:
using Newtonsoft.Json.Linq;
using System;
using System.Globalization;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace ConsoleApp
{
class Program
{
static string NH_NAMESPACE = "{Please input}";
static string HUB_NAME = "{Please input}";
static string KEY_NAME = "DefaultFullSharedAccessSignature";
static string KEY_VALUE = "{Please input}";
static void Main(string[] args)
{
JObject jobject = new JObject();
jobject.Add("text1", "my app");
jobject.Add("text2", "my value");
SendNotificaitonAsync(jobject.ToString()).Wait();
Console.ReadLine();
}
private static async Task SendNotificaitonAsync(string content)
{
string resourceUri = $"https://{NH_NAMESPACE}.servicebus.windows.net/{HUB_NAME}/messages/";
using (var request = CreateHttpRequest(HttpMethod.Post, resourceUri))
{
request.Content = new StringContent(content, Encoding.UTF8, "application/octet-stream");
request.Content.Headers.ContentType.CharSet = string.Empty;
var httpClient = new HttpClient();
var response = await httpClient.SendAsync(request);
Console.WriteLine(response.StatusCode);
}
}
private static HttpRequestMessage CreateHttpRequest(HttpMethod method, String resourceUri)
{
var request = new HttpRequestMessage(method, $"{resourceUri}?api-version=2017-04");
request.Headers.Add("Authorization", createToken(resourceUri, KEY_NAME, KEY_VALUE));
request.Headers.Add("X-WNS-Type", "wns/raw");
request.Headers.Add("ServiceBusNotification-Format", "windows");
return request;
}
private static string createToken(string resourceUri, string keyName, string key)
{
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var week = 60 * 60 * 24 * 7;
var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + week);
string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
return sasToken;
}
}
}