Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Molnservern kan skicka ett push-meddelande till din app via Windows Push Notification Services (WNS). Den här proceduren gäller för panel-, popup-, märkes- och råa push-meddelanden.
Syfte: Skapa och skicka en platta, toastavisering, märke eller ett rått push-meddelande.
Förutsättningar
För att förstå det här ämnet eller för att använda den kod som det innehåller behöver du:
- Kunskaper om HTTP-kommunikation.
- En autentiserad molnserver. Mer information finns i Autentisera med Windows Push Notification Service (WNS).
- En registrerad kanal som molnservern kan kommunicera med din app över. Mer information finns i Så här begär, skapar och sparar du en meddelandekanal.
- En befintlig panel för din app, definierad i appens manifest, för att ta emot meddelandet (såvida du inte skickar ett raw-meddelande). Mer information finns i Snabbstart: Skapa en standardpanel med hjälp av Microsoft Visual Studio-manifestredigeraren.
- Kunskaper om XML och dess manipulering via API:er för dokumentobjektmodell (DOM).
- När det gäller råa meddelanden måste appen konfigureras för att ta emot råa meddelanden. Mer information finns i Snabbstart: Intercepta push-meddelanden för körande appar och Snabbstart: Skapa och registrera en bakgrundsuppgift för råa meddelanden.
Instruktion
1. Inkludera nödvändiga namnområdesreferenser
Exemplen i det här avsnittet kan användas as-is, men kräver att koden innehåller följande namnområdesreferenser:
using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Text;
2. Skapa en HTTP POST-begäran
Parametern uri
är den kanal-URI (Uniform Resource Identifier) som har begärts av appen och skickats till molnservern. Mer information finns i Så här begär, skapar och sparar du en meddelandekanal.
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";
3. Lägg till de nödvändiga rubrikerna
Det finns fyra obligatoriska rubriker som måste ingå i alla push-meddelanden: X-WNS-Type, Content-Type, Content-Length och Authorization.
- Rubriken X-WNS-Type anger om det här är en panel, ett popup-meddelande, ett märke eller ett råmeddelande.
- Innehållstypen anges beroende på värdet för X-WNS-Type.
- Innehållslängden ger storleken på den inkluderade meddelandenyttolasten.
- Auktoriseringshuvudet anger autentiseringsuppgifterna som gör att du kan skicka ett push-meddelande till den här användaren via den här kanalen.
Parametern accessToken i auktoriseringshuvudet anger den åtkomsttoken som lagras på servern och som togs emot från WNS när molnservern begärde autentisering. Utan åtkomsttoken avvisas ditt meddelande.
För en fullständig lista över möjliga huvuden, se begäran och svarshuvuden för push-meddelandetjänsten.
request.Headers.Add("X-WNS-Type", notificationType);
request.ContentType = contentType;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));
4. Lägg till det förberedda innehållet
När det gäller HTTP-begäran är XML-innehållet i meddelandet en datablob i begärandetexten. Det görs till exempel ingen verifiering av att XML-koden matchar X-WNS-Type-specifikationen. Innehållet anges som en XML-nyttolast och här läggs det till i begäran som en ström med byte.
byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
5. Lyssna efter ett svar från WNS som bekräftar mottagandet av meddelandet
Anmärkning
Du får aldrig en leveransbekräftelse för ett meddelande, bara en bekräftelse på att den togs emot av WNS.
using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
return webResponse.StatusCode.ToString();
6. Hantera WNS-svarskoder
Det finns många svarskoder som apptjänsten kan ta emot när den skickar ett meddelande. Vissa av dessa svarskoder är vanligare än andra och kan enkelt hanteras i ett catch-block.
catch (WebException webException)
{
HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;
HttpStatusCode.Unauthorized: Åtkomsttoken som du presenterade har upphört att gälla. Hämta en ny och försök sedan skicka meddelandet igen. Eftersom din cachelagrade åtkomsttoken upphör att gälla efter 24 timmar kan du förvänta dig att få det här svaret från WNS minst en gång om dagen. Vi rekommenderar att du implementerar en princip för maximalt återförsök.
if (status == HttpStatusCode.Unauthorized)
{
GetAccessToken(secret, sid);
return PostToWns(uri, xml, secret, sid, notificationType, contentType);
}
HttpStatusCode.Gone/HttpStatusCode.NotFound: Kanal-URI:n är inte längre giltig. Ta bort den här kanalen från databasen för att förhindra ytterligare försök att skicka meddelanden till den. Nästa gång den här användaren startar din app begär du en ny WNS-kanal. Din app bör identifiera att dess kanal har ändrats, vilket bör utlösa appen för att skicka den nya kanal-URI:n till appservern. Mer information finns i Så här begär, skapar och sparar du en meddelandekanal.
else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound)
{
return "";
}
HttpStatusCode.NotAcceptable: Den här kanalen begränsas av WNS. Implementera en återförsöksstrategi som exponentiellt minskar mängden meddelanden som skickas för att förhindra att begränsas igen. Omvärdera också de scenarier som gör att dina meddelanden begränsas. Du kommer att ge en bättre användarupplevelse genom att begränsa de meddelanden du skickar till dem som lägger till verkligt värde.
else if (status == HttpStatusCode.NotAcceptable)
{
return "";
}
Andra svarskoder: WNS svarade med en mindre vanlig svarskod. Logga den här koden för att hjälpa till med felsökning. En fullständig lista över WNS-svarskoder finns i Begäran och svarshuvuden för push-meddelanden .
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. Kapsla in koden i en enda funktion
I följande exempel paketeras koden som anges i föregående steg i en enda funktion. Den här funktionen består av HTTP POST-begäran som innehåller ett meddelande som ska skickas till WNS. Genom att ändra värdet för typparametern och justera ytterligare rubriker kan den här koden användas för popup-meddelanden, paneler, märken eller råa push-meddelanden. Du kan använda den här funktionen som en del av molnserverkoden.
Observera att felhanteringen i den här funktionen omfattar den situation där åtkomsttoken har upphört att gälla. I det här fallet anropas en annan molnserverfunktion som autentiserar igen med WNS för att hämta en ny åtkomsttoken. Den gör sedan ett nytt anrop till den ursprungliga funktionen.
// 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);
}
Följande visar exempelinnehåll för en HTTP POST-begäran för ett toast push-meddelande.
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>
Följande visar ett exempel på HTTP-svar som skickas till molnservern av WNS som svar på HTTP POST-begäran.
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
Sammanfattning
I den här snabbstarten har du skapat en HTTP POST-begäran om att skicka till WNS. WNS levererar i sin tur meddelandet till din app. Nu har du registrerat din app, autentiserat molnservern med WNS, skapat XML-innehåll för att definiera ditt meddelande och skickat meddelandet från servern till din app.
Relaterade ämnen
Windows developer