Rychlý start: Odeslání push oznámení (XAML)

Váš cloudový server může odeslat push oznámení vaší aplikaci prostřednictvím Windows Push Notification Services (WNS). Tento postup platí pro dlaždice, plovoucí oznámení, odznáčky a nezpracovaná oznámení.

cíl : Vytvoření a odeslání dlaždice, informační zprávy, odznáčku nebo surového push oznámení.

Prerequisites

Pokud chcete porozumět tomuto tématu nebo použít kód, který poskytuje, budete potřebovat:

Instructions

1. Zahrňte potřebné odkazy na jmenný prostor.

Příklady uvedené v tomto tématu lze použít as-is, ale vyžadují, aby váš kód obsahoval tyto odkazy na namespace:

using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Text;

2. Vytvoření požadavku HTTP POST

Parametrem uri je identifikátor URI (Uniform Resource Identifier) kanálu požadovaný aplikací a předaný cloudovému serveru. Další informace najdete v tématu Jak požádat, vytvořit a uložit kanál oznámení.

HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";

3. Přidejte požadované hlavičky.

Ve všech push oznámeních musí být zahrnuta čtyři povinná záhlaví: X-WNS-Type, Content-Type, Content-Length, a Authorization.

  • Hlavička typu X-WNS-Type určuje, jestli se jedná o dlaždici, toast, odznak nebo oznámení ve formátu raw.
  • Typ obsahu se nastavuje v závislosti na hodnotě typu X-WNS.
  • Délka obsahu udává velikost zahrnuté datové části oznámení.
  • Hlavička Autorizace určuje ověřovací údaje, které vám umožní odeslat push notifikaci tomuto uživateli přes tento kanál.

Parametr accessToken hlavičky autorizace určuje přístupový token uložený na serveru, který byl přijat ze služby WNS, když cloudový server požadoval ověření. Bez přístupového tokenu se vaše oznámení odmítne.

Pro úplný seznam možných hlaviček si prohlédněte hlavičky požadavků a odpovědí služby oznámení push.

request.Headers.Add("X-WNS-Type", notificationType);
request.ContentType = contentType;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));

4. Přidání připraveného obsahu

Pokud jde o požadavek HTTP, obsah XML oznámení je datový blob v textu požadavku. Například není provedeno žádné ověření, že XML odpovídá specifikaci X-WNS-Type. Obsah je specifikován jako XML datová část a je přidán do požadavku jako stream bajtů.

byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);
                        
using (Stream requestStream = request.GetRequestStream())
    requestStream.Write(contentInBytes, 0, contentInBytes.Length);

5. Poslechněte si odpověď od služby WNS, která potvrzuje přijetí oznámení.

Note

Nikdy neobdržíte potvrzení o doručení oznámení, pouze potvrzení o přijetí oznámení službou WNS.

using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
    return webResponse.StatusCode.ToString();

6. Zpracování kódů odpovědí WNS

Existuje mnoho kódů odpovědí, které může služba App Service přijímat při odesílání oznámení. Některé z těchto kódů odpovědí jsou častější než jiné a dají se snadno zpracovat v bloku catch.

catch (WebException webException)
{
    HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;

HttpStatusCode.Unauthorized: Přístupový token, který jste předložili, vypršel. Získejte nový a zkuste oznámení odeslat znovu. Vzhledem k tomu, že platnost přístupového tokenu uloženého v mezipaměti vyprší po 24 hodinách, můžete očekávat, že odpověď služby WNS obdržíte alespoň jednou denně. Doporučujeme implementovat zásady maximálního opakování.

    if (status == HttpStatusCode.Unauthorized)
    {
        GetAccessToken(secret, sid);
        return PostToWns(uri, xml, secret, sid, notificationType, contentType);
    }

HttpStatusCode.Gone / HttpStatusCode.NotFound: Identifikátor URI kanálu už není platný. Odeberte tento kanál z databáze, abyste zabránili dalším pokusům o odeslání oznámení. Při příštím spuštění aplikace požádejte o nový kanál WNS. Aplikace by měla zjistit, že se kanál změnil, což by mělo aktivovat aplikaci, aby odeslala nový identifikátor URI kanálu na váš aplikační server. Další informace najdete v tématu Jak požádat, vytvořit a uložit kanál oznámení.

    else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound)
    {
        return "";
    }

HttpStatusCode.NotAcceptable: Služba WNS omezuje tento kanál. Implementujte strategii opakování, která exponenciálně snižuje množství odesílaných oznámení, aby se zabránilo tomu, že budou znovu omezeny. Zvažte také scénáře, které způsobují omezování vašich oznámení. Tím, že omezíte oznámení odesílaná na ty, které přidají skutečnou hodnotu, poskytnete bohatší uživatelské prostředí.

    else if (status == HttpStatusCode.NotAcceptable)
    {
        return "";
    }

Další kódy odpovědí: WNS odpověděl s méně běžným kódem odpovědi. Uložte tento kód kvůli ladění. Úplný seznam kódů odpovědí WNS naleznete v sekci žádost o službu oznámení a hlavičky odpovědí.

    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. Zapouzdření kódu do jedné funkce

Následující příklad zabalí kód uvedený v předchozích krocích do jedné funkce. Tato funkce vytvoří požadavek HTTP POST, který obsahuje oznámení, které se má odeslat do služby WNS. Změnou hodnoty typu parametru a úpravou dalších hlaviček se tento kód dá použít pro informační zprávy, dlaždici, odznáček nebo nezpracovaná nabízená oznámení. Tuto funkci můžete použít jako součást kódu cloudového serveru.

Všimněte si, že zpracování chyb v této funkci zahrnuje situaci, kdy vypršela platnost přístupového tokenu. V tomto případě volá jinou funkci cloudového serveru, která se znovu ověřuje pomocí služby WNS, aby získala nový přístupový token. Potom provede nové volání původní funkce.

// 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);
}

Následující text ukazuje příklad obsahu požadavku HTTP POST pro oznámení typu toast.

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>

Následující příklad ukazuje odpověď HTTP odeslanou službou WNS na cloudový server v reakci na požadavek 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

V tomto rychlém startu jste složili požadavek HTTP POST pro odeslání do služby WNS. WNS zase doručí oznámení do vaší aplikace. V tomto okamžiku jste aplikaci zaregistrovali, ověřili jste cloudový server pomocí služby WNS, vytvořili jste obsah XML pro definování vašeho oznámení a odeslali toto oznámení ze serveru do vaší aplikace.