Rychlý start: Push oznámení ve Windows App SDK

V tomto rychlém startu vytvoříte desktopovou Windows aplikaci, která odesílá a přijímá nabízená oznámení pomocí Windows App SDK.

Prerequisites

Požadavky na balení

Nabízená oznámení v Windows App SDK podporují zabalené i skutečně rozbalené desktopové aplikace. Identita balíčku se ale vyžaduje pro doručování na pozadí a aktivaci modelu COM – nejběžnější produkční scénář. Následující tabulka shrnuje, co je potřeba na základě modelu balení:

Model balení Vyžaduje se aktivátor COM. Vyžaduje se mapování PFN Rozbalené podporované
MSIX zabalený (WinUI 3, zabalený WPF (Windows Presentation Foundation)/WinForms) Ano – v Package.appxmanifest Ano – prostřednictvím mapování PFN e-mailem Ne
Zabaleno s externím umístěním Ano – v Package.appxmanifest Ano – prostřednictvím mapování PFN e-mailem Ne
Skutečně rozbaleno (bez identity balíčku) Ne (přeskočit krok 3) Ne Ano – omezené funkce

Important

Pokud je vaše aplikace zabalena (MSIX nebo zabalena s externím umístěním), musíte namapovat Název rodiny balíčku (PFN) na jeho Azure AppId předtím, než budou oznámení fungovat. Žádosti o mapování se odesílají e-mailem Win_App_SDK_Push@microsoft.com a zpracovávají se každý týden. Naplánujte si tuto časovou rezervu před spuštěním.

Podrobnosti najdete v tématu Krok 4: Namapování názvu rodiny balíčků vaší aplikace na její Azure AppId.

Ukázková aplikace

Tento rychlý návod vás provede přidáním podpory push oznámení do vaší aplikace v rámci Windows App SDK 1.7. Podívejte se na podobný kód jako v tomto rychlém startu v ukázkových aplikacích nalezených na GitHub. Nezapomeňte si prohlédnout branch s upřednostňovanou verzí Windows App SDK pro ukázky, které nejlépe odpovídají vašemu projektu.

Ukázky pro každou verzi Windows App SDK najdete také výběrem větve verze v úložišti ukázek.

Referenční informace k rozhraní API

Referenční dokumentaci k rozhraní API pro push oznámení najdete v tématu Microsoft.Windows.PushNotifications Obor názvů.

Konfigurace identity aplikace v Azure Active Directory (AAD)

Nabízená oznámení v Windows App SDK používají identity z Azure Active Directory (AAD). Azure přihlašovací údaje jsou vyžadovány při vyžádání identifikátoru URI kanálu WNS a při vyžádání přístupových tokenů, aby bylo možné odesílat nabízená oznámení. Poznámka: Nepodporujeme použití push notifikací Windows App SDK s Partnerské centrum Microsoftu.

Krok 1: Vytvoření registrace aplikace AAD

Přihlaste se ke svému účtu Azure a vytvořte nový prostředek AD App Registration. Vyberte Nová registrace.

Krok 2: Zadejte název a vyberte možnost s více tenanty

  1. Zadejte název aplikace.

  2. Oznámení push vyžadují variantu s více nájemci, takže ji vyberte.

    1. Další informace o tenantech najdete v tématu Kdo se může přihlásit k vaší aplikaci?.
  3. Vyberte Zaregistrovat

  4. Poznamenejte si ID aplikace Application (client), protože se jedná o id Azure AppId, které budete používat při registraci aktivace a žádosti o přístupový token.

  5. Poznamenejte si ID adresáře (tenanta), protože se jedná o ID Azure tenanta, které budete používat, když žádáte o přístupový token.

    Important

    Registrace aplikace AAD tenanta poznamenejte si ID aplikace (klienta) a ID adresáře (tenanta) .

  6. Poznamenejte si id objektu Objektu, protože se jedná o id objektu Azure, které budete používat při žádosti o kanál. Všimněte si, že se nejedná o ID objektu uvedené na stránce Základy . Pokud chcete najít správné ID objektu , klikněte na název aplikace v poli spravované aplikace v místním adresáři na stránce Essentials:

    Snímek obrazovky znázorňující možnost Spravovaná aplikace v místním adresáři na stránce Základy

    Snímek obrazovky s polem ID objektu

    Note

    Pro získání ID objektu je vyžadována služební identita, pokud k aplikaci není přidružen žádný objekt, postupujte podle pokynů v jednom z následujících článků a vytvořte ji na portálu Azure nebo pomocí příkazového řádku.

    Použití portálu k vytvoření aplikace Azure AD a instančního objektu, který má přístup k prostředkům

    Použijte Azure PowerShell k vytvoření služebního účtu s certifikátem

Krok 3: Vytvoření tajného kódu pro registraci aplikace

Váš tajný kód se použije společně s vaším Azure AppId/ClientId při vyžádání přístupového tokenu k odesílání nabízených oznámení.

tajný klíč aplikace AAD

Přejděte na Certifikáty a tajné kódy a vyberte Nový tajný klíč klienta.

Important

Ujistěte se, že po vytvoření zkopírujete tajný kód a uložíte ho do bezpečného umístění, jako je Azure Key Vault. Bude se zobrazovat jenom jednou po vytvoření.

Krok 4: Mapování názvu rodiny balíčků vaší aplikace na jeho Azure AppId

Pokud je vaše aplikace balená (včetně balení pro externí umístění), můžete pomocí tohoto procesu namapovat název rodiny balíčků vaší aplikace (PFN) a její Azure AppId.

Pokud je vaše aplikace balíčkovou aplikací Win32, vytvořte žádost o mapování názvu rodiny balíčků (PFN) zasláním e-mailu na Win_App_SDK_Push@microsoft.com s předmětem "Žádost o mapování oznámení Windows App SDK" a textem "PFN: [váš PFN], AppId: [váš AppId], ObjectId: [váš ObjectId]". Žádosti o mapování jsou dokončeny každý týden. Jakmile bude vaše žádost o mapování hotová, zobrazí se vám oznámení.

Jakmile budete mít Azure AppId, ObjectId a tajný kód, můžete tyto přihlašovací údaje přidat do ukázkového kódu níže.

Nakonfigurujte svou aplikaci pro příjem push oznámení

Krok 1: Přidání Windows App SDK a požadovaných balíčků NuGet

Dále klikněte pravým tlačítkem na řešení v Průzkumníku řešení a vyberte Spravovat balíčky NuGet.

Do Správce balíčků přidejte následující balíčky:

  • Microsoft. WindowsAppSDK (minimálně verze 1.1.0)
  • Microsoft. Windows. SDK. BuildTools (minimální verze 10.0.22000.194)
  • Microsoft. Windows. CppWinRT, (minimální verze 2.0.210930.14)
  • Microsoft. Windows. ImplementationLibrary, (minimálně verze 1.0.210930.1)

Pokud je to poprvé, co ve svém projektu používáte Windows App SDK a je zabalený s externím umístěním nebo je nebalený, inicializujte Windows App SDK přidáním následující vlastnosti do souboru projektu:

<!-- your .vcxproj or .proj file -->
<PropertyGroup Label="Globals">
    <!-- Other properties -->
    <WindowsPackageType>None</WindowsPackageType>
</PropertyGroup>

nebo použijte rozhraní API bootstrapperu. Další podrobnosti najdete v tématu Použití runtime Windows App SDK pro aplikace balené s externím umístěním nebo nebalené.

Note

Pokud sada SDK není inicializována, aplikace vyvolá System.Runtime.InteropServices.COMException (0x80040154): Class not registered (0x80040154 (REGDB_E_CLASSNOTREG)) a nespustí se.

Krok 2: Přidání jmenných prostorů

Dále přidejte obor názvů pro push oznámení Windows App SDK Microsoft.Windows.PushNotifications.

#include <winrt/Microsoft.Windows.PushNotifications.h>

using namespace winrt::Microsoft::Windows::PushNotifications;

Pokud se zobrazí chyba "Nelze najít Microsoft.Windows.PushNotifications", pravděpodobně to znamená, že nebyly vygenerovány soubory hlaviček. Pokud chcete tento problém vyřešit, ujistěte se, že máte nainstalované výše uvedené balíčky, zakomentujte příkazy include a using, které způsobují chybu, a znovu sestavte aplikaci, aby vygenerovala soubory hlaviček. Jakmile sestavení proběhne úspěšně, odkomentujte příkazy include a using a znovu sestavte projekt. Tím by se měla tato chyba vyřešit.

Krok 3: Přidání aktivátoru COM do manifestu aplikace

Important

Pokud je vaše aplikace nebalená (tj. nemá identitu balíčku při běhu), přejděte ke kroku 4: Registrace a reakce na push oznámení při spuštění aplikace.

Pokud je vaše aplikace zabalená (včetně zabalení s externím umístěním): Otevřete Package.appxmanifest. Do elementu <Application> přidejte následující kód. Nahraďte hodnoty Id, Executable a DisplayName hodnotami specifickými pro vaši aplikaci.

<!--Packaged apps only-->
<!--package.appxmanifest-->

<Package
  ...
  xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
  ...
  <Applications>
    <Application>
      ...
      <Extensions>

        <!--Register COM activator-->    
        <com:Extension Category="windows.comServer">
          <com:ComServer>
              <com:ExeServer Executable="SampleApp\SampleApp.exe" DisplayName="SampleApp" Arguments="----WindowsAppRuntimePushServer:">
                <com:Class Id="[Your app's Azure AppId]" DisplayName="Windows App SDK Push" />
            </com:ExeServer>
          </com:ComServer>
        </com:Extension>
    
      </Extensions>
    </Application>
  </Applications>
 </Package>    

Note

Atribut Id v <com:Class> musí být nastavený na Azure AppId (ID aplikace (klienta) z vaší registrace aplikace Azure AD). Takto Windows App SDK propojí aktivaci vašeho COM modelu s Azure identitou – když služba WNS aktivuje vaši aplikaci k doručení push oznámení na pozadí, použije tento identifikátor GUID k vyhledání a spuštění správného COM serveru. Použijte stejnou hodnotu Azure AppId, kterou jste si poznamenali v kroku 1 výše.

Note

Příklad dokončené třídy C++ pro tento příklad lze najít po kroku 5. Kroky 4 a 5 obsahují podrobné pokyny k přidání jednotlivých kroků v posledním příkladu.

Krok 4: Registrace a reakce na nabízená oznámení při spuštění aplikace

Aktualizujte metodu main() aplikace tak, aby přidala následující:

  1. Zaregistrujte aplikaci pro příjem push oznámení voláním PushNotificationManager::Default().Register().
  2. Zkontrolujte zdroj žádosti o aktivaci voláním AppInstance::GetCurrent(). GetActivatedEventArgs(). Pokud byla aktivace spuštěna z push oznámení, odpovězte na základě datové části oznámení.

Important

Musíte volat PushNotificationManager::D efault(). Zaregistrujte před voláním AppInstance.GetCurrent.GetActivatedEventArgs.

Přidání obslužných rutin událostí popředí

Pokud chcete zpracovat událost v popředí, zaregistrujte obslužnou rutinu pro PushNotificationManager.PushReceived.

Important

Před voláním PushNotificationManager.Register() musíte také zaregistrovat všechny obslužné rutiny událostí PushNotificationManager.PushReceived . Jinak se vyvolá následující výjimka modulu runtime:

System.Runtime.InteropServices.COMException: Element not found. Must register event handlers before calling Register().

Přidání kontroly PushNotificationManager::IsSupported()

Dále přidejte kontrolu, jestli jsou rozhraní API PushNotification podporována pomocí PushNotificationManager.IsSupported(). Pokud ne, doporučujeme použít dotazování nebo vlastní implementaci socketů.

Teď, když je potvrzená podpora push oznámení, přidejte chování na základě PushNotificationReceivedEventArgs.

Krok 5: Vyžádání identifikátoru URI kanálu WNS a jeho registrace na serveru WNS

Identifikátory URI kanálu WNS jsou koncové body HTTP pro odesílání nabízených oznámení. Každý klient musí požádat o identifikátor URI kanálu a zaregistrovat ho u serveru WNS, aby dostával nabízená oznámení.

Note

Identifikátory URI kanálu WNS vyprší po 30 dnech. Při každém spuštění aplikace požádejte o nový identifikátor URI kanálu namísto ukládání předchozího do mezipaměti. Když se nový identifikátor URI liší od toho, co váš back-end uložil, odešle aktualizovaný identifikátor URI do cloudové služby, aby mohl uchovávat aktuální záznamy. Nepředpokládáme, že identifikátor URI zůstane mezi relacemi stabilní – považuje ho za proměnlivou hodnotu s rozsahem relace, aby se zabránilo selhání tichého doručení způsobené vypršením platnosti nebo zastaralými identifikátory URI kanálu.

auto channelOperation{ PushNotificationManager::Default().CreateChannelAsync(winrt::guid("[Your app's Azure ObjectID]")) };

Pokud sledujete kód kurzu, přidejte id objektu Azure sem:

// To obtain an AAD RemoteIdentifier for your app,
// follow the instructions on https://learn.microsoft.com/azure/active-directory/develop/quickstart-register-app
winrt::guid remoteId{ "00000000-0000-0000-0000-000000000000" }; // Replace this with your own Azure ObjectId

PushNotificationManager se pokusí vytvořit identifikátor URI kanálu a automaticky to zkusí znovu po dobu maximálně 15 minut. Vytvořte obslužnou rutinu události, která bude čekat na dokončení volání. Po dokončení volání zaregistrujte identifikátor URI na serveru WNS.

Příklad kódu

#include <iostream>
#include <winrt/Microsoft.Windows.PushNotifications.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Microsoft.Windows.AppLifecycle.h>
#include <winrt/Windows.ApplicationModel.Background.h>
#include <wil/cppwinrt.h>
#include <wil/result.h>

using namespace winrt::Microsoft::Windows::PushNotifications;
using namespace winrt::Windows::Foundation;
using namespace winrt::Microsoft::Windows::AppLifecycle;

// To obtain an AAD RemoteIdentifier for your app,
// follow the instructions on https://learn.microsoft.com/azure/active-directory/develop/quickstart-register-app
winrt::guid remoteId{ "00000000-0000-0000-0000-000000000000" }; // Replace this with your own Azure ObjectId

winrt::Windows::Foundation::IAsyncOperation<PushNotificationChannel> RequestChannelAsync()
{
    auto channelOperation = PushNotificationManager::Default().CreateChannelAsync(remoteId);

    // Set up the in-progress event handler
    channelOperation.Progress(
        [](auto&& sender, auto&& args)
        {
            if (args.status == PushNotificationChannelStatus::InProgress)
            {
                // This is basically a noop since it isn't really an error state
                std::cout << "Channel request is in progress." << std::endl << std::endl;
            }
            else if (args.status == PushNotificationChannelStatus::InProgressRetry)
            {
                LOG_HR_MSG(
                    args.extendedError,
                    "The channel request is in back-off retry mode because of a retryable error! Expect delays in acquiring it. RetryCount = %d",
                    args.retryCount);
            }
        });

    auto result = co_await channelOperation;

    if (result.Status() == PushNotificationChannelStatus::CompletedSuccess)
    {
        auto channelUri = result.Channel().Uri();

        std::cout << "channelUri: " << winrt::to_string(channelUri.ToString()) << std::endl << std::endl;

        auto channelExpiry = result.Channel().ExpirationTime();

        // Caller's responsibility to keep the channel alive
        co_return result.Channel();
    }
    else if (result.Status() == PushNotificationChannelStatus::CompletedFailure)
    {
        LOG_HR_MSG(result.ExtendedError(), "We hit a critical non-retryable error with channel request!");
        co_return nullptr;
    }
    else
    {
        LOG_HR_MSG(result.ExtendedError(), "Some other failure occurred.");
        co_return nullptr;
    }

};

PushNotificationChannel RequestChannel()
{
    auto task = RequestChannelAsync();
    if (task.wait_for(std::chrono::seconds(300)) != AsyncStatus::Completed)
    {
        task.Cancel();
        return nullptr;
    }

    auto result = task.GetResults();
    return result;
}

void SubscribeForegroundEventHandler()
{
    winrt::event_token token{ PushNotificationManager::Default().PushReceived([](auto const&, PushNotificationReceivedEventArgs const& args)
    {
        auto payload{ args.Payload() };

        std::string payloadString(payload.begin(), payload.end());
        std::cout << "\nPush notification content received in the FOREGROUND: " << payloadString << std::endl;
    }) };

    std::cout << "Push notification foreground event handler registered." << std::endl;
}

int main()
{
    // Set up an event handler, so we can receive notifications in the foreground while the app is running.
    // You must register notification event handlers before calling Register(). Otherwise, the following runtime
    // exception will be thrown: System.Runtime.InteropServices.COMException: 'Element not found. Must register
    // event handlers before calling Register().'
    SubscribeForegroundEventHandler();

    // Register the app for push notifications.
    PushNotificationManager::Default().Register();

    auto args{ AppInstance::GetCurrent().GetActivatedEventArgs() };
    switch (args.Kind())
    {
        case ExtendedActivationKind::Launch:
        {
            std::cout << "App launched by user or from the debugger." << std::endl;
            if (PushNotificationManager::IsSupported())
            {
                std::cout << "Push notifications are supported on this device." << std::endl;

                // Request a WNS Channel URI which can be passed off to an external app to send notifications to.
                // The WNS Channel URI uniquely identifies this app for this user and device.
                PushNotificationChannel channel{ RequestChannel() };
                if (!channel)
                {
                    std::cout << "\nThere was an error obtaining the WNS Channel URI" << std::endl;

                    if (remoteId == winrt::guid{ "00000000-0000-0000-0000-000000000000" })
                    {
                        std::cout << "\nThe ObjectID has not been set. Refer to the readme file accompanying this sample\nfor the instructions on how to obtain and setup an ObjectID" << std::endl;
                    }
                }

                std::cout << "\nPress 'Enter' at any time to exit App." << std::endl;
                std::cin.ignore();
            }
            else
            {
                std::cout << "Push notifications are NOT supported on this device." << std::endl;
                std::cout << "App implements its own custom socket here to receive messages from the cloud since Push APIs are unsupported." << std::endl;
                std::cin.ignore();
            }
        }
        break;

        case ExtendedActivationKind::Push:
        {
            std::cout << "App activated via push notification." << std::endl;
            PushNotificationReceivedEventArgs pushArgs{ args.Data().as<PushNotificationReceivedEventArgs>() };

            // Call GetDeferral to ensure that code runs in low power
            auto deferral{ pushArgs.GetDeferral() };

            auto payload{ pushArgs.Payload() };

            // Do stuff to process the raw notification payload
            std::string payloadString(payload.begin(), payload.end());
            std::cout << "\nPush notification content received in the BACKGROUND: " << payloadString.c_str() << std::endl;
            std::cout << "\nPress 'Enter' to exit the App." << std::endl;

            // Call Complete on the deferral when finished processing the payload.
            // This removes the override that kept the app running even when the system was in a low power mode.

            deferral.Complete();
            std::cin.ignore();
        }
        break;

        default:
            std::cout << "\nUnexpected activation type" << std::endl;
            std::cout << "\nPress 'Enter' to exit the App." << std::endl;
            std::cin.ignore();
            break;
    }
}

Krok 6: Sestavení a instalace aplikace

K sestavení a instalaci aplikace použijte Visual Studio. Klikněte pravým tlačítkem na soubor řešení v Průzkumník řešení a vyberte Deploy. Visual Studio aplikaci sestaví a nainstaluje na počítač. Aplikaci můžete spustit tak, že ji spustíte pomocí nabídky Start nebo Visual Studio Debugger.

Konzola kódu kurzu bude vypadat takto:

funkční ukázková konzola

K odeslání nabízeného oznámení do aplikace budete potřebovat token.

Odeslání nabízeného oznámení do aplikace

V tuto chvíli je veškerá konfigurace dokončená a server WNS může odesílat nabízená oznámení klientským aplikacím. V následujících krocích se odkazujte na hlavičky požadavků a odpovědí push notifikačního serveru a pro bližší informace.

Krok 1: Vyžádání přístupového tokenu

Pokud chcete odeslat nabízené oznámení, musí server WNS nejprve požádat o přístupový token. Odešlete požadavek HTTP POST s ID tenanta Azure, Azure AppId a tajným kódem. Informace o načtení Azure TenantId a Azure AppId najdete v tématu Získání hodnot ID tenanta a aplikace pro přihlášení.

Ukázkový požadavek HTTP:

POST /{tenantID}/oauth2/v2.0/token Http/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 160

grant_type=client_credentials&client_id=<Azure_App_Registration_AppId_Here>&client_secret=<Azure_App_Registration_Secret_Here>&scope=https://wns.windows.com/.default/

Ukázkový požadavek jazyka C#:

//Sample C# Access token request
var client = new RestClient("https://login.microsoftonline.com/{tenantID}/oauth2/v2.0");
var request = new RestRequest("/token", Method.Post);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("client_id", "[Your app's Azure AppId]");
request.AddParameter("client_secret", "[Your app's secret]");
request.AddParameter("scope", "https://wns.windows.com/.default");
RestResponse response = await client.ExecutePostAsync(request);
Console.WriteLine(response.Content);

Pokud je vaše žádost úspěšná, obdržíte odpověď, která obsahuje váš token v poli access_token .

{
    "token_type":"Bearer",
    "expires_in":"86399",
    "ext_expires_in":"86399",
    "expires_on":"1653771789",
    "not_before":"1653685089",
    "access_token":"[your access token]"
}

Krok 2. Odeslání nezpracovaného oznámení

Vytvořte požadavek HTTP POST obsahující přístupový token, který jste získali v předchozím kroku, a obsah nabízeného oznámení, které chcete odeslat. Obsah push oznámení bude doručen do aplikace.

POST /?token=[The token query string parameter from your channel URL. E.g. AwYAAABa5cJ3...] HTTP/1.1
Host: dm3p.notify.windows.com
Content-Type: application/octet-stream
X-WNS-Type: wns/raw
Authorization: Bearer [your access token]
Content-Length: 46

{ Sync: "Hello from the Contoso App Service" }
var client = new RestClient("[Your channel URL. E.g. https://wns2-by3p.notify.windows.com/?token=AwYAAABa5cJ3...]");
var request = new RestRequest();
request.Method = Method.Post; 
request.AddHeader("Content-Type", "application/octet-stream");
request.AddHeader("X-WNS-Type", "wns/raw");
request.AddHeader("Authorization", "Bearer [your access token]");
request.AddBody("Notification body");
RestResponse response = await client.ExecutePostAsync(request);");

Krok 3: Odeslání oznámení o cloudové zdrojové aplikaci

Pokud vás zajímá jenom odesílání nezpracovaných oznámení, ignorujte tento krok. Pokud chcete odeslat oznámení aplikace z cloudu, známé také jako push oznámení typu toast, nejprve postupujte podle Quickstart: Oznámení aplikací ve Windows App SDK. Oznámení aplikací můžou být nabízená (odesílaná z cloudu) nebo místně odesílaná. Odeslání oznámení aplikace zdrojového do cloudu se podobá odeslání nezpracovaného oznámení v kroku 2s výjimkou záhlaví typu X-WNS typu je toast, Content-Type je text/xmla obsah obsahuje datovou část XML oznámení aplikace. Další informace o tom, jak sestavit datovou část XML, najdete v tématu XML schéma oznámení.

Vytvořte požadavek HTTP POST, který obsahuje váš přístupový token a obsah oznámení cloudové aplikace, které chcete odeslat. Obsah push oznámení bude doručen do aplikace.

POST /?token=AwYAAAB%2fQAhYEiAESPobjHzQcwGCTjHu%2f%2fP3CCNDcyfyvgbK5xD3kztniW%2bjba1b3aSSun58SA326GMxuzZooJYwtpgzL9AusPDES2alyQ8CHvW94cO5VuxxLDVzrSzdO1ZVgm%2bNSB9BAzOASvHqkMHQhsDy HTTP/1.1
Host: dm3p.notify.windows.com
Content-Type: text/xml
X-WNS-Type: wns/toast
Authorization: Bearer [your access token]
Content-Length: 180

<toast><visual><binding template="ToastGeneric"><text>Example cloud toast notification</text><text>This is an example cloud notification using XML</text></binding></visual></toast>
var client = new RestClient("https://dm3p.notify.windows.com/?token=AwYAAAB%2fQAhYEiAESPobjHzQcwGCTjHu%2f%2fP3CCNDcyfyvgbK5xD3kztniW%2bjba1b3aSSun58SA326GMxuzZooJYwtpgzL9AusPDES2alyQ8CHvW94cO5VuxxLDVzrSzdO1ZVgm%2bNSB9BAzOASvHqkMHQhsDy");
client.Timeout = -1;

var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "text/xml");
request.AddHeader("X-WNS-Type", "wns/toast");
request.AddHeader("Authorization", "Bearer <AccessToken>");
request.AddParameter("text/xml", "<toast><visual><binding template=\"ToastGeneric\"><text>Example cloud toast notification</text><text>This is an example cloud notification using XML</text></binding></visual></toast>",  ParameterType.RequestBody);
Console.WriteLine(response.Content);

Resources