Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Twój serwer w chmurze jest w stanie wysyłać powiadomienia push do Twojej aplikacji za pośrednictwem usług powiadomień systemu Windows (WNS). Ta procedura dotyczy kafelka, powiadomień typu toast, znaczka i nieprzetworzonych powiadomień push.
Cel: Utworzyć i wysłać kafelek, powiadomienie, znaczek lub powiadomienie push.
Wymagania wstępne
Aby zrozumieć ten temat lub użyć kodu, który zawiera, potrzebne są następujące elementy:
- Znajomość komunikacji HTTP.
- Uwierzytelniony serwer w chmurze. Aby uzyskać więcej informacji, zobacz Jak uwierzytelniać się za pomocą usługi powiadomień wypychanych systemu Windows (WNS).
- Zarejestrowany kanał, za pośrednictwem którego serwer w chmurze może komunikować się z twoją aplikacją. Aby uzyskać więcej informacji, zobacz Jak zażądać, utworzyć i zapisać kanał powiadomień.
- Istniejący kafelek aplikacji zdefiniowany w manifeście aplikacji w celu odbierania powiadomienia (chyba że wysyłasz nieprzetworzone powiadomienie). Aby uzyskać więcej informacji, zobacz Szybki start: tworzenie domyślnego kafelka przy użyciu edytora manifestu programu Microsoft Visual Studio.
- Znajomość kodu XML i manipulowania nimi za pośrednictwem interfejsów API modelu obiektów dokumentów (DOM).
- W przypadku nieprzetworzonych powiadomień aplikacja musi być skonfigurowana do odbierania nieprzetworzonych powiadomień. Aby uzyskać więcej informacji, zobacz Szybki start: przechwytywanie powiadomień wypychanych na potrzeby uruchamiania aplikacjii Szybki start: tworzenie i rejestrowanie nieprzetworzonego zadania w tle powiadomień.
Instrukcje
1. Dołącz niezbędne odwołania do przestrzeni nazw
Przykłady podane w tym temacie mogą być używane, ale wymagają, aby kod zawierał następujące odwołania do przestrzeni nazw: as-is.
using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Text;
2. Tworzenie żądania HTTP POST
Parametr uri
to kanał Uniform Resource Identifier (URI) żądany przez aplikację i przekazany do serwera w chmurze. Aby uzyskać więcej informacji, zobacz Jak zażądać, utworzyć i zapisać kanał powiadomień.
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";
3. Dodaj wymagane nagłówki
Istnieją cztery wymagane nagłówki, które muszą być uwzględnione we wszystkich powiadomieniach wypychanych: X-WNS-Type, Content-Type, Content-Length i Authorization.
- Nagłówek X-WNS-Type określa, czy jest to kafelek, wyskakujące, znaczek lub nieprzetworzone powiadomienie.
- Typ zawartości jest ustawiany w zależności od wartości X-WNS-Type.
- Właściwość Content-Length określa rozmiar zawartego ładunku danych powiadomień.
- Nagłówek Autoryzacja określa poświadczenie uwierzytelniające, które umożliwia wysyłanie powiadomień push do tego użytkownika tym kanałem.
Parametr accessToken nagłówka Authorization określa token dostępu przechowywany na serwerze, który został odebrany z usługi WNS, gdy serwer w chmurze zażądał uwierzytelnienia. Bez tokenu dostępu powiadomienie zostanie odrzucone.
Aby uzyskać pełną listę możliwych nagłówków, zobacz Push notification service request and response headers (Żądania usługi powiadomień wypychanych i nagłówki odpowiedzi).
request.Headers.Add("X-WNS-Type", notificationType);
request.ContentType = contentType;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));
4. Dodawanie przygotowanej zawartości
Jeśli chodzi o żądanie HTTP, zawartość XML powiadomienia jest zbiorem danych w treści żądania. Na przykład nie dokonano weryfikacji, że kod XML jest zgodny ze specyfikacją X-WNS-Type. Zawartość jest określana jako ładunek XML i tutaj jest dodawana do żądania jako strumień bajtów.
byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
5. Oczekuj odpowiedzi z usługi WNS, która potwierdza otrzymanie powiadomienia
Uwaga / Notatka
Nigdy nie otrzymasz potwierdzenia dostarczenia dla powiadomienia, po prostu potwierdzenie, że zostało odebrane przez usługę WNS.
using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
return webResponse.StatusCode.ToString();
6. Obsługa kodów odpowiedzi usługi WNS
Istnieje wiele kodów odpowiedzi, które usługa App Service może odbierać po wysłaniu powiadomienia. Niektóre z tych kodów odpowiedzi są bardziej powszechne niż inne i mogą być łatwo obsługiwane w bloku catch.
catch (WebException webException)
{
HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;
HttpStatusCode.Unauthorized: wyświetlony token dostępu wygasł. Pobierz nowy, a następnie spróbuj ponownie wysłać powiadomienie. Ponieważ buforowany token dostępu wygasa po 24 godzinach, możesz oczekiwać, że ta odpowiedź będzie uzyskiwana z usługi WNS co najmniej raz dziennie. Zalecamy zaimplementowanie maksymalnych zasad ponawiania prób.
if (status == HttpStatusCode.Unauthorized)
{
GetAccessToken(secret, sid);
return PostToWns(uri, xml, secret, sid, notificationType, contentType);
}
HttpStatusCode.Gone / HttpStatusCode.NotFound: Identyfikator URI kanału nie jest już prawidłowy. Usuń ten kanał z bazy danych, aby uniemożliwić dalsze próby wysłania do niej powiadomienia. Następnym razem, gdy ten użytkownik uruchomi aplikację, zażądaj nowego kanału WNS. Aplikacja powinna wykryć, że jej kanał uległ zmianie, co powinno spowodować wysłanie nowego identyfikatora URI kanału do serwera aplikacji. Aby uzyskać więcej informacji, zobacz Jak zażądać, utworzyć i zapisać kanał powiadomień.
else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound)
{
return "";
}
HttpStatusCode.NotAcceptable: ten kanał jest ograniczany przez usługę WNS. Zaimplementuj strategię ponawiania, która wykładniczo zmniejsza liczbę wysyłanych powiadomień, aby zapobiec ponownemu ograniczaniu przepustowości. Rozważ również scenariusze, które powodują ograniczanie powiadomień. Zapewnisz bogatsze doświadczenie użytkownika, ograniczając powiadomienia do tych, które rzeczywiście dodają prawdziwą wartość.
else if (status == HttpStatusCode.NotAcceptable)
{
return "";
}
Inne kody odpowiedzi: WNS odpowiedział mniej typowym kodem odpowiedzi. Zarejestruj ten kod, aby ułatwić debugowanie. Aby uzyskać pełną listę kodów odpowiedzi WNS, zobacz Nagłówki żądań i odpowiedzi usługi powiadomień 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. Hermetyzowanie kodu w jedną funkcję
Poniższy przykład pakuje kod podany w poprzednich krokach do pojedynczej funkcji. Ta funkcja komponuje żądanie HTTP POST zawierające powiadomienie wysyłane do usługi WNS. Zmieniając wartość parametru typu i dostosowując dodatkowe nagłówki, ten kod może być użyty do powiadomień toast, kafelki, odznaki lub surowych powiadomień push. Tej funkcji można używać jako części kodu serwera w chmurze.
Należy pamiętać, że obsługa błędów w tej funkcji obejmuje sytuację, w której token dostępu wygasł. W takim przypadku wywołuje inną funkcję serwera w chmurze, która ponownie uwierzytelnia się w usłudze WNS, aby uzyskać nowy token dostępu. Następnie wykonuje nowe wywołanie oryginalnej funkcji.
// 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);
}
Poniżej przedstawiono przykładową zawartość żądania HTTP POST dla powiadomienia 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>
Poniżej przedstawiono przykładową odpowiedź HTTP wysłaną do serwera w chmurze przez usługę WNS w odpowiedzi na żądanie 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
Podsumowanie
W tej sekcji Quickstart utworzono żądanie HTTP POST, aby wysłać je do usługi WNS. Z kolei usługa WNS dostarcza powiadomienie do aplikacji. W tym momencie zarejestrowano aplikację, uwierzytelniono serwer w chmurze za pomocą usługi WNS, utworzono zawartość XML w celu zdefiniowania powiadomienia i wysłano to powiadomienie z serwera do aplikacji.