Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Облачный сервер может отправлять push-уведомление приложению через службы push-уведомлений Windows (WNS). Эта процедура применяется к плитке, всплывающему элементу, значку и необработанным push-уведомлениям.
Цель: Создать и отправить плиточное уведомление, тост, значок или сырое push-уведомление.
Prerequisites
Чтобы понять этот раздел или использовать указанный код, вам потребуется:
- Знакомство с http-коммуникациями.
- Прошедший проверку подлинности облачный сервер. Дополнительные сведения см. в статье "Проверка подлинности с помощью службы push-уведомлений Windows (WNS)".
- Зарегистрированный канал, по которому облачный сервер может взаимодействовать с приложением. Дополнительные сведения см. в статье "Как запрашивать, создавать и сохранять канал уведомлений".
- Существующая плитка для приложения, определенная в манифесте приложения, для получения уведомления (если вы не отправляете необработанное уведомление). Для получения дополнительной информации смотрите Краткое руководство: создание плитки по умолчанию с помощью редактора манифеста Microsoft Visual Studio.
- Знакомство с XML и его манипуляцией с помощью API-интерфейсов объектной модели документов (DOM).
- В случае необработанных уведомлений приложение должно быть настроено для получения необработанных уведомлений. Дополнительные сведения см. в кратком руководстве: Перехват push-уведомлений для работающих приложений и в кратком руководстве: Создание и регистрация фоновой задачи необработанного уведомления.
Instructions
1. Включите необходимые ссылки на пространство имен
Примеры, приведенные в этом разделе, можно использовать as-is, но требуется, чтобы код включал следующие ссылки на пространство имен:
using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Text;
2. Создание HTTP-запроса POST
Параметр uri — это универсальный код ресурса канала (URI), запрашиваемый приложением, и передается на облачный сервер. Дополнительные сведения см. в статье "Как запрашивать, создавать и сохранять канал уведомлений".
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";
3. Добавление обязательных заголовков
Существует четыре обязательных заголовка, которые должны быть включены во все push-уведомления: X-WNS-Type, Content-Type, Content-Length и Authorization.
- Заголовок X-WNS-Type
указывает, является ли это плитка, всплывающее уведомление, индикатор событий или необработанное уведомление. - Тип контента задается в зависимости от значения X-WNS-Type.
- Поле Content-Length указывает размер полезных данных, включенных в уведомление.
- Заголовок авторизации
указывает креденты аутентификации, позволяющие отправить push-уведомление этому пользователю по этому каналу.
Параметр accessToken заголовка Authorization указывает маркер доступа, хранящийся на сервере, который был получен от WNS, когда облачный сервер запрашивал аутентификацию. Без токена доступа уведомление будет отклонено.
Полный список возможных заголовков см. в разделе "Запрос службы push-уведомлений" и заголовки ответа.
request.Headers.Add("X-WNS-Type", notificationType);
request.ContentType = contentType;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));
4. Добавление подготовленного содержимого
Что касается HTTP-запроса, xml-содержимое уведомления представляет собой большой двоичный объект данных в тексте запроса. Например, не выполняется проверка соответствия XML спецификации X-WNS-Type. Содержимое указывается как XML-полезная нагрузка и добавляется в запрос в виде потока байтов.
byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
5. Прослушивание ответа от WNS, которое подтверждает получение уведомления
Note
Вы никогда не получите подтверждение доставки для уведомления, просто подтверждение того, что оно было получено WNS.
using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
return webResponse.StatusCode.ToString();
6. Обработка кодов ответов WNS
Существует множество кодов откликов, которые служба приложений может получать при отправке уведомления. Некоторые из этих кодов ответов более распространены, чем другие, и их можно легко решать в блоке catch.
catch (WebException webException)
{
HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;
HttpStatusCode.Unauthorized: срок действия указанного токена доступа истёк. Получите новый, а затем повторите попытку отправки уведомления. Так как срок действия кэшированного маркера доступа истекает через 24 часа, вы можете ожидать получения ответа от WNS по крайней мере один раз в день. Рекомендуется реализовать максимальную политику повторных попыток.
if (status == HttpStatusCode.Unauthorized)
{
GetAccessToken(secret, sid);
return PostToWns(uri, xml, secret, sid, notificationType, contentType);
}
HttpStatusCode.Gone / HttpStatusCode.NotFound: URI канала больше недействителен. Удалите этот канал из базы данных, чтобы предотвратить дальнейшие попытки отправки уведомления в него. При следующем запуске вашего приложения запросите новый канал WNS. Приложение должно обнаружить, что его канал изменился, что должно активировать приложение для отправки нового URI канала на сервер приложений. Дополнительные сведения см. в статье "Как запрашивать, создавать и сохранять канал уведомлений".
else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound)
{
return "";
}
HttpStatusCode.NotAcceptable: этот канал регулируется WNS. Реализуйте стратегию повторных попыток, которая экспоненциально уменьшает количество отправляемых уведомлений, чтобы избежать повторного ограничения. Кроме того, переосмыслите сценарии, которые вызывают регулирование уведомлений. Вы предоставите более богатый пользовательский опыт, ограничив уведомления только теми, которые действительно полезны.
else if (status == HttpStatusCode.NotAcceptable)
{
return "";
}
другие коды ответа: WNS ответил с менее стандартным кодом ответа. Запишите этот код, чтобы помочь в отладке. Полный список кодов ответов WNS см. в разделе заголовков запросов и ответов службы push-уведомлений.
else
{
string[] debugOutput = {
status.ToString(),
webException.Response.Headers["X-WNS-Debug-Trace"],
webException.Response.Headers["X-WNS-Error-Description"],
webException.Response.Headers["X-WNS-Msg-ID"],
webException.Response.Headers["X-WNS-Status"]
};
return string.Join(" | ", debugOutput);
}
7. Инкапсулировать код в одну функцию
В следующем примере код, приведенный на предыдущих шагах, упаковается в одну функцию. Эта функция создает HTTP-запрос POST, содержащий уведомление, которое отправляется в WNS. Изменив значение параметра типа
Обратите внимание, что обработка ошибок в этой функции включает ситуацию, когда срок действия маркера доступа истек. В этом случае он вызывает другую облачную функцию сервера, которая повторно выполняет проверку подлинности с помощью WNS, чтобы получить новый маркер доступа. Затем он создает новый вызов исходной функции.
// Post to WNS
public string PostToWns(string secret, string sid, string uri, string xml, string notificationType, string contentType)
{
try
{
// You should cache this access token.
var accessToken = GetAccessToken(secret, sid);
byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";
request.Headers.Add("X-WNS-Type", notificationType);
request.ContentType = contentType;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
return webResponse.StatusCode.ToString();
}
catch (WebException webException)
{
HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;
if (status == HttpStatusCode.Unauthorized)
{
// The access token you presented has expired. Get a new one and then try sending
// your notification again.
// Because your cached access token expires after 24 hours, you can expect to get
// this response from WNS at least once a day.
GetAccessToken(secret, sid);
// We recommend that you implement a maximum retry policy.
return PostToWns(uri, xml, secret, sid, notificationType, contentType);
}
else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound)
{
// The channel URI is no longer valid.
// Remove this channel from your database to prevent further attempts
// to send notifications to it.
// The next time that this user launches your app, request a new WNS channel.
// Your app should detect that its channel has changed, which should trigger
// the app to send the new channel URI to your app server.
return "";
}
else if (status == HttpStatusCode.NotAcceptable)
{
// This channel is being throttled by WNS.
// Implement a retry strategy that exponentially reduces the amount of
// notifications being sent in order to prevent being throttled again.
// Also, consider the scenarios that are causing your notifications to be throttled.
// You will provide a richer user experience by limiting the notifications you send
// to those that add true value.
return "";
}
else
{
// WNS responded with a less common error. Log this error to assist in debugging.
// You can see a full list of WNS response codes here:
// https://msdn.microsoft.com/library/windows/apps/hh868245.aspx#wnsresponsecodes
string[] debugOutput = {
status.ToString(),
webException.Response.Headers["X-WNS-Debug-Trace"],
webException.Response.Headers["X-WNS-Error-Description"],
webException.Response.Headers["X-WNS-Msg-ID"],
webException.Response.Headers["X-WNS-Status"]
};
return string.Join(" | ", debugOutput);
}
}
catch (Exception ex)
{
return "EXCEPTION: " + ex.Message;
}
}
// Authorization
[DataContract]
public class OAuthToken
{
[DataMember(Name = "access_token")]
public string AccessToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
}
private OAuthToken GetOAuthTokenFromJson(string jsonString)
{
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
var ser = new DataContractJsonSerializer(typeof(OAuthToken));
var oAuthToken = (OAuthToken)ser.ReadObject(ms);
return oAuthToken;
}
}
protected OAuthToken GetAccessToken(string secret, string sid)
{
var urlEncodedSecret = HttpUtility.UrlEncode(secret);
var urlEncodedSid = HttpUtility.UrlEncode(sid);
var body = String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com",
urlEncodedSid,
urlEncodedSecret);
string response;
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
response = client.UploadString("https://login.live.com/accesstoken.srf", body);
}
return GetOAuthTokenFromJson(response);
}
В следующем примере показан пример содержимого запроса HTTP POST для всплывающего push-уведомления.
POST https://db3.notify.windows.com/?token=AgUAAADCQmTg7OMlCg%2fK0K8rBPcBqHuy%2b1rTSNPMuIzF6BtvpRdT7DM4j%2fs%2bNNm8z5l1QKZMtyjByKW5uXqb9V7hIAeA3i8FoKR%2f49ZnGgyUkAhzix%2fuSuasL3jalk7562F4Bpw%3d HTTP/1.1
Authorization: Bearer EgAaAQMAAAAEgAAACoAAPzCGedIbQb9vRfPF2Lxy3K//QZB79mLTgK
X-WNS-RequestForStatus: true
X-WNS-Type: wns/toast
Content-Type: text/xml
Host: db3.notify.windows.com
Content-Length: 196
<toast launch="">
<visual lang="en-US">
<binding template="ToastImageAndText01">
<image id="1" src="World" />
<text id="1">Hello</text>
</binding>
</visual>
</toast>
Ниже показан пример HTTP-ответа, отправляемого на облачный сервер WNS в ответ на HTTP-запрос POST.
HTTP/1.1 200 OK
Content-Length: 0
X-WNS-DEVICECONNECTIONSTATUS: connected
X-WNS-STATUS: received
X-WNS-MSG-ID: 3CE38FF109E03A74
X-WNS-DEBUG-TRACE: DB3WNS4011534
Summary
В этом руководстве по быстрому запуску вы создали POST-запрос HTTP для отправки в WNS. WNS, в свою очередь, предоставляет уведомление приложению. К этому моменту вы зарегистрировали приложение, выполнили проверку подлинности облачного сервера с помощью WNS, создали XML-содержимое для определения уведомления и отправили это уведомление с сервера в приложение.
Related topics
Windows developer