Azure 通知中心:如何从 .net 后端向单个用户发送本地化的、平台无关的推送通知?
Azure Notification Hubs: How to send localized, platform independent push notifications to individual users from a .net backend?
场景
我正在为本地化的跨平台移动应用程序开发后端,并希望在后端发生某些事件时向用户发送推送通知。
这些应用程序是为 iOS 和 android 使用 xamarin,后端是一个 web-api 2,它使用 Azure 通知中心.
目前的工作
目前,移动应用程序使用 Installations 通过 Web-API 注册通知。通过 web-API 注册是必要的,因为服务器会创建一个唯一的用户标签,用于在发送消息时识别用户。我目前能够从 Azure 后端的“调试”部分向注册的 iOS 设备发送测试通知。这是处理注册的代码:
[HttpPut]
[Route("")]
public async Task<IHttpActionResult> CreateOrUpdateDeviceInstallation(DeviceInstallationModel deviceInstallationModel)
{
var installation = new Installation
{
InstallationId = deviceInstallationModel.InstallationId,
PushChannel = deviceInstallationModel.Handle
};
switch (deviceInstallationModel.Platform)
{
case "apns":
installation.Platform = NotificationPlatform.Apns;
break;
case "gcm":
installation.Platform = NotificationPlatform.Gcm;
break;
default:
return BadRequest("The given platform is not supported");
}
installation.Tags = new List<string>{ OwnerId };
//OwnerId is the server generated unique user tag
await _notificationHubClient.CreateOrUpdateInstallationAsync(installation);
return Ok();
}
public class DeviceInstallationModel
{
public string InstallationId { get; set; }
public string Platform { get; set; }
public string Handle { get; set; }
}
我的问题
我现在需要在后端发生某些事件时发送 localized 推送通知。我正在尝试实现这一点 ,而后端对应用程序的区域设置或应用程序的平台一无所知。据我从文档 (Cross-Platform-Notifications and localized-notifications) 中了解到,templates 将让我实现这一点。
我的问题
- 如何使用安装完成模板注册?
- 模板必须是什么样子才能在客户端本地化?客户端必须做什么才能实现本地化? (或者是否有每个语言环境的模板?)
- 在不知道客户端平台或语言环境的情况下,后端必须做什么才能发送通知?
- 我有不同的消息(文本)要发送。每条消息都需要一个(甚至更多)模板吗?
要回答1-3,你会想看看Template feature. (Q1) Since you are using Mobile Apps, the Mobile Apps Xamarin SDKs actually allows you to register with templates in Installations directly. (Q2) To see what a template looks like in an Installation object, the body here是个好地方。 (Q3) 要发送,您链接到的教程实际上提供了很好的示例。
对于第四季度,这真的取决于。您可以使用相同的模板来传达不同的消息,因为使用此模板注册的所有用户都会收到这些消息(例如,在 cross-plat tutorial 中,您可以轻松地切换到 "Hello,"+ 用户并使用另一条消息)。但是如果您需要将这些消息本地化等,您将需要多个模板。
如果您有任何其他问题,请告诉我。
我找到了实现所需行为的解决方案。
出于演示目的,假设客户端可以注册两个不同的通知,MessageA 和 MessageB。 MessageA 从客户端标记为 "tagForMessageA",MessageB 从客户端标记为 "taggedForMessageB" 。当客户端应用程序启动或用户更改其语言时,它会调用 web-API 并为其要接收的每条消息指定 one 模板(本例中为 messageA 和 messageB) .正文包含 平台特定的本地化正文 ,例如:
MessageA, 英文iOS
{"aps":{"alert":"This is message A!"}}
或
MessageB,德语 android
{"data":{"message":"Dies ist NachrichtB für Android!"}}
这使客户能够决定
- 它想要接收什么消息
- 消息使用的语言
- 如何显示它们。
通过API
注册
现在这是处理注册的 web-API 代码:
API 控制器
[HttpPut]
[Route("")]
public async Task<IHttpActionResult> CreateOrUpdateDeviceInstallation(DeviceInstallationModel deviceInstallationModel)
{
var installation = new Installation
{
InstallationId = deviceInstallationModel.InstallationId,
PushChannel = deviceInstallationModel.Handle,
Tags = new List<string>
{
//Obtain the users id from the database here
},
Templates = new Dictionary<string, InstallationTemplate>()
};
switch (deviceInstallationModel.Platform)
{
case "apns":
installation.Platform = NotificationPlatform.Apns;
break;
case "gcm":
installation.Platform = NotificationPlatform.Gcm;
break;
default:
return BadRequest("The given platform is not supported");
}
foreach (var templateModel in deviceInstallationModel.Templates)
{
if (installation.Templates.ContainsKey(templateModel.MessageIdentifier))
{
return BadRequest("Message identifiers must be unique");
}
installation.Templates.Add(
templateModel.MessageIdentifier,
CreateInstallationTemplateFromModel(templateModel));
}
await _notificationHubClient.CreateOrUpdateInstallationAsync(installation);
return Ok();
}
private static InstallationTemplate CreateInstallationTemplateFromModel(TemplateModel templateModel)
{
return new InstallationTemplate
{
Body = templateModel.Body,
Tags = new List<string> {templateModel.MessageIdentifier}
};
}
型号
public class DeviceInstallationModel
{
public DeviceInstallationModel()
{
Templates= new List<TemplateModel>();
}
public string InstallationId { get; set; }
public string Platform { get; set; }
public string Handle { get; set; }
public List<TemplateModel> Templates { get; set; }
}
public class TemplateModel
{
public string MessageIdentifier { get; set; }
public string Body { get; set; }
}
消息标识符
这是客户也必须遵守的约定:
public class MessageIdentifiers
{
public const string MessageA = "tagForMessageA";
public const string MessageB = "tagForMessageB";
}
从后端发送消息
此代码处理向客户端发送通知
消息A
public void SendMessageA(int recipientUserId)
{
var tagExpression = $"{recipientUserId}&&{MessageIdentifiers.MessageA}";
_notificationHubClient.SendTemplateNotificationAsync(new Dictionary<string, string>(),
tagExpression);
}
消息B
public void SendMessageB(int recipientUserId)
{
var tagExpression = $"{recipientUserId}&&{MessageIdentifiers.MessageB}";
_notificationHubClient.SendTemplateNotificationAsync(new Dictionary<string, string>(),
tagExpression);
}
- How is the template registration done using Installations?
正如您已经在自己的答案中使用的那样,使用 Templates
property of the Installation
class.
- How must a template look like in order to be localizable on the client and what must a client do to achieve localization? (Or is there a template per locale?)
对需要本地化的文本使用模板参数,并为参数名称添加语言后缀。更准确地说,客户应该使用带有语言后缀参数的模板进行注册。
iOS 英语语言环境示例:
{"aps":{"alert":"$(message_en)"}}
Android 德语语言环境示例:
{"data":{"message":"$(message_de)"}}
- What must the backend do to send notifications while not knowing the clients platform or locale?
只需在所有可能的语言环境中发送包含所有参数的模板通知。
假设应用程序仅支持英语和德语的示例:
public void SendMessageA(int recipientUserId)
{
var tagExpression = $"{recipientUserId}";
var parameters = new Dictionary<string, string>()
{
{ "message_en", "This is message A!" },
{ "message_de", "Dies ist Nachricht A!" }
};
_notificationHubClient.SendTemplateNotificationAsync(parameters, tagExpression);
}
public void SendMessageB(int recipientUserId)
{
var tagExpression = $"{recipientUserId}";
var parameters = new Dictionary<string, string>()
{
{ "message_en", "This is message B!" },
{ "message_de", "Dies ist Nachricht B!" }
};
_notificationHubClient.SendTemplateNotificationAsync(parameters, tagExpression);
}
- I have different messages (text) to send. Do I need one (or even more) templates for each message?
如您所见,通过这种方法,您可以为每个应用程序实例注册一个模板,并可以从后端发送不同的本地化消息。
当然,你的答案中的方法也有效,但你应该尽可能避免使用标签,因为标签表达式是有限的(例如 to 6 tags, if the expression contains other operators than OR
),如果你不这样做,你会更灵活将通知文本硬编码到您的应用中。
场景
我正在为本地化的跨平台移动应用程序开发后端,并希望在后端发生某些事件时向用户发送推送通知。
这些应用程序是为 iOS 和 android 使用 xamarin,后端是一个 web-api 2,它使用 Azure 通知中心.
目前的工作
目前,移动应用程序使用 Installations 通过 Web-API 注册通知。通过 web-API 注册是必要的,因为服务器会创建一个唯一的用户标签,用于在发送消息时识别用户。我目前能够从 Azure 后端的“调试”部分向注册的 iOS 设备发送测试通知。这是处理注册的代码:
[HttpPut]
[Route("")]
public async Task<IHttpActionResult> CreateOrUpdateDeviceInstallation(DeviceInstallationModel deviceInstallationModel)
{
var installation = new Installation
{
InstallationId = deviceInstallationModel.InstallationId,
PushChannel = deviceInstallationModel.Handle
};
switch (deviceInstallationModel.Platform)
{
case "apns":
installation.Platform = NotificationPlatform.Apns;
break;
case "gcm":
installation.Platform = NotificationPlatform.Gcm;
break;
default:
return BadRequest("The given platform is not supported");
}
installation.Tags = new List<string>{ OwnerId };
//OwnerId is the server generated unique user tag
await _notificationHubClient.CreateOrUpdateInstallationAsync(installation);
return Ok();
}
public class DeviceInstallationModel
{
public string InstallationId { get; set; }
public string Platform { get; set; }
public string Handle { get; set; }
}
我的问题
我现在需要在后端发生某些事件时发送 localized 推送通知。我正在尝试实现这一点 ,而后端对应用程序的区域设置或应用程序的平台一无所知。据我从文档 (Cross-Platform-Notifications and localized-notifications) 中了解到,templates 将让我实现这一点。
我的问题
- 如何使用安装完成模板注册?
- 模板必须是什么样子才能在客户端本地化?客户端必须做什么才能实现本地化? (或者是否有每个语言环境的模板?)
- 在不知道客户端平台或语言环境的情况下,后端必须做什么才能发送通知?
- 我有不同的消息(文本)要发送。每条消息都需要一个(甚至更多)模板吗?
要回答1-3,你会想看看Template feature. (Q1) Since you are using Mobile Apps, the Mobile Apps Xamarin SDKs actually allows you to register with templates in Installations directly. (Q2) To see what a template looks like in an Installation object, the body here是个好地方。 (Q3) 要发送,您链接到的教程实际上提供了很好的示例。 对于第四季度,这真的取决于。您可以使用相同的模板来传达不同的消息,因为使用此模板注册的所有用户都会收到这些消息(例如,在 cross-plat tutorial 中,您可以轻松地切换到 "Hello,"+ 用户并使用另一条消息)。但是如果您需要将这些消息本地化等,您将需要多个模板。
如果您有任何其他问题,请告诉我。
我找到了实现所需行为的解决方案。
出于演示目的,假设客户端可以注册两个不同的通知,MessageA 和 MessageB。 MessageA 从客户端标记为 "tagForMessageA",MessageB 从客户端标记为 "taggedForMessageB" 。当客户端应用程序启动或用户更改其语言时,它会调用 web-API 并为其要接收的每条消息指定 one 模板(本例中为 messageA 和 messageB) .正文包含 平台特定的本地化正文 ,例如:
MessageA, 英文iOS
{"aps":{"alert":"This is message A!"}}
或 MessageB,德语 android
{"data":{"message":"Dies ist NachrichtB für Android!"}}
这使客户能够决定
- 它想要接收什么消息
- 消息使用的语言
- 如何显示它们。
通过API
注册现在这是处理注册的 web-API 代码:
API 控制器
[HttpPut]
[Route("")]
public async Task<IHttpActionResult> CreateOrUpdateDeviceInstallation(DeviceInstallationModel deviceInstallationModel)
{
var installation = new Installation
{
InstallationId = deviceInstallationModel.InstallationId,
PushChannel = deviceInstallationModel.Handle,
Tags = new List<string>
{
//Obtain the users id from the database here
},
Templates = new Dictionary<string, InstallationTemplate>()
};
switch (deviceInstallationModel.Platform)
{
case "apns":
installation.Platform = NotificationPlatform.Apns;
break;
case "gcm":
installation.Platform = NotificationPlatform.Gcm;
break;
default:
return BadRequest("The given platform is not supported");
}
foreach (var templateModel in deviceInstallationModel.Templates)
{
if (installation.Templates.ContainsKey(templateModel.MessageIdentifier))
{
return BadRequest("Message identifiers must be unique");
}
installation.Templates.Add(
templateModel.MessageIdentifier,
CreateInstallationTemplateFromModel(templateModel));
}
await _notificationHubClient.CreateOrUpdateInstallationAsync(installation);
return Ok();
}
private static InstallationTemplate CreateInstallationTemplateFromModel(TemplateModel templateModel)
{
return new InstallationTemplate
{
Body = templateModel.Body,
Tags = new List<string> {templateModel.MessageIdentifier}
};
}
型号
public class DeviceInstallationModel
{
public DeviceInstallationModel()
{
Templates= new List<TemplateModel>();
}
public string InstallationId { get; set; }
public string Platform { get; set; }
public string Handle { get; set; }
public List<TemplateModel> Templates { get; set; }
}
public class TemplateModel
{
public string MessageIdentifier { get; set; }
public string Body { get; set; }
}
消息标识符
这是客户也必须遵守的约定:
public class MessageIdentifiers
{
public const string MessageA = "tagForMessageA";
public const string MessageB = "tagForMessageB";
}
从后端发送消息
此代码处理向客户端发送通知
消息A
public void SendMessageA(int recipientUserId)
{
var tagExpression = $"{recipientUserId}&&{MessageIdentifiers.MessageA}";
_notificationHubClient.SendTemplateNotificationAsync(new Dictionary<string, string>(),
tagExpression);
}
消息B
public void SendMessageB(int recipientUserId)
{
var tagExpression = $"{recipientUserId}&&{MessageIdentifiers.MessageB}";
_notificationHubClient.SendTemplateNotificationAsync(new Dictionary<string, string>(),
tagExpression);
}
- How is the template registration done using Installations?
正如您已经在自己的答案中使用的那样,使用 Templates
property of the Installation
class.
- How must a template look like in order to be localizable on the client and what must a client do to achieve localization? (Or is there a template per locale?)
对需要本地化的文本使用模板参数,并为参数名称添加语言后缀。更准确地说,客户应该使用带有语言后缀参数的模板进行注册。
iOS 英语语言环境示例:
{"aps":{"alert":"$(message_en)"}}
Android 德语语言环境示例:
{"data":{"message":"$(message_de)"}}
- What must the backend do to send notifications while not knowing the clients platform or locale?
只需在所有可能的语言环境中发送包含所有参数的模板通知。
假设应用程序仅支持英语和德语的示例:
public void SendMessageA(int recipientUserId)
{
var tagExpression = $"{recipientUserId}";
var parameters = new Dictionary<string, string>()
{
{ "message_en", "This is message A!" },
{ "message_de", "Dies ist Nachricht A!" }
};
_notificationHubClient.SendTemplateNotificationAsync(parameters, tagExpression);
}
public void SendMessageB(int recipientUserId)
{
var tagExpression = $"{recipientUserId}";
var parameters = new Dictionary<string, string>()
{
{ "message_en", "This is message B!" },
{ "message_de", "Dies ist Nachricht B!" }
};
_notificationHubClient.SendTemplateNotificationAsync(parameters, tagExpression);
}
- I have different messages (text) to send. Do I need one (or even more) templates for each message?
如您所见,通过这种方法,您可以为每个应用程序实例注册一个模板,并可以从后端发送不同的本地化消息。
当然,你的答案中的方法也有效,但你应该尽可能避免使用标签,因为标签表达式是有限的(例如 to 6 tags, if the expression contains other operators than OR
),如果你不这样做,你会更灵活将通知文本硬编码到您的应用中。