Öğretici: Azure Notification Hubs kullanarak belirli kullanıcılara anında iletme bildirimleri gönderme

Bu öğreticide, belirli bir cihazdaki belirli bir uygulama kullanıcısına anında iletme bildirimleri göndermek için Azure Bildirim Hubs’ı nasıl kullanacağınız gösterilmektedir. ASP.NET WebAPI arka ucu, uygulama arka ucunuzdan kaydolma kılavuz konusunda gösterildiği gibi istemcilerin kimliğini doğrulamak ve bildirimler oluşturmak için kullanılır.

Bu öğreticide, aşağıdaki adımları gerçekleştireceksiniz:

  • WebAPI projesi oluşturma
  • WebAPI arka ucunda istemcilerin kimliğini doğrulama
  • WebAPI arka ucunu kullanarak bildirimlere kaydolma
  • WebAPI arka ucundan bildirim gönderme
  • Yeni WebAPI arka ucunu yayımlama
  • iOS uygulamanızı değiştirme
  • Uygulamayı test edin

Önkoşullar

Bu öğreticide, Azure Notification Hubs kullanarak iOS uygulamalarına anında iletme bildirimleri gönderme başlığında açıklandığı gibi bildirim hub'ınızı oluşturduğunuz ve yapılandırdığınız varsayılır. Bu öğretici, Güvenli Gönderme (iOS) öğreticisinin de önkoşuludur. Arka uç hizmetiniz olarak Mobile Apps'i kullanmak istiyorsanız bkz. Mobile Apps Göndermeye Başlama.

WebAPI projesi oluşturma

Aşağıdaki bölümlerde, yeni bir ASP.NET WebAPI arka ucu oluşturma işlemi açıklanmaktadır. Bu işlemin üç ana amacı vardır:

  • İstemcilerin kimliğini doğrulama: İstemci isteklerinin kimliğini doğrulamak ve kullanıcıyı istekle ilişkilendirmek üzere bir ileti işleyicisi eklersiniz.
  • WebAPI arka ucunu kullanarak bildirimlere kaydolma: Bir istemci cihazının bildirimleri alması için yeni kayıtları işlemek üzere bir denetleyici eklersiniz. Kimliği doğrulanmış kullanıcı adı, otomatik olarak kayda bir etiket halinde eklenir.
  • İstemcilere bildirimleri gönderme: Kullanıcıların etiketle ilişkili cihazlara ve istemcilere güvenli bir gönderimi tetiklemesi için yeni bir yol sağlamak üzere bir denetleyici de eklersiniz.

Aşağıdaki eylemleri gerçekleştirerek yeni ASP.NET Core 6.0 web API'sinin arka ucu oluşturun:

Denetlemek için Visual Studio’yu başlatın. Araçlar menüsünde Uzantılar ve Güncelleştirmeler’i seçin. Visual Studio sürümünüz için NuGet Paket Yöneticisi araması yapın ve en son sürümü kullandığınızdan emin olun. Sürümünüz en son sürüm değilse, bunu kaldırın ve NuGet Paket Yöneticisi'ni yeniden yükleyin.

Visual Studios için NuGet Paketi yönet paketinin vurgulandığı Uzantılar ve Güncelleştirmeler iletişim kutusunun ekran görüntüsü.

Not

Web sitesi dağıtımı için Visual Studio Azure SDK'sını yüklediğinizden emin olun.

  1. Visual Studio veya Visual Studio Express’i başlatın.

  2. Sunucu Gezgini’ni seçip Azure hesabınızda oturum açın. Hesabınızda web sitesi kaynakları oluşturmak için oturum açmanız gerekir.

  3. Visual Studio'nun Dosya menüsünde Yeni Proje'yi> seçin.

  4. Arama kutusuna Web API'sini girin.

  5. ASP.NET Core Web API proje şablonunu seçin ve İleri'yi seçin.

  6. Yeni projenizi yapılandırın iletişim kutusunda projeyi AppBackend olarak adlandırın ve İleri'yi seçin.

  7. Ek bilgiler iletişim kutusunda:

    • Framework'ün.NET 6.0 (Uzun vadeli destek) olduğunu onaylayın.
    • Denetleyicileri kullan (en az API kullanmak için işaretini kaldır) onay kutusunun işaretli olduğunu onaylayın.
    • OpenAPI desteğini etkinleştir seçeneğinin işaretini kaldırın.
    • Oluştur’u seçin.

WeatherForecast şablon dosyalarını kaldırma

  1. Yeni AppBackend projesinden WeatherForecast.cs ve Controllers/WeatherForecastController.cs örnek dosyalarını kaldırın.
  2. Properties\launchSettings.json dosyasını açın.
  3. launchUrl özelliklerini weatherforcast olan appbackend olarak değiştirin.

Microsoft Azure Web App’i yapılandırma penceresinde, bir abonelik seçin ve App Service planı listesinde aşağıdaki eylemlerden birini yapın:

  • Önceden oluşturduğunuz bir Azure App Service planı seçin.
  • Yeni bir App Service planı oluştur’u seçin ve yeni bir plan oluşturun.

Bu öğretici için bir veritabanı gerekmez. App Service planınızı seçtikten sonra projeyi oluşturmak için Tamam’ı seçin.

Microsoft Azure Web App’i Yapılandırma penceresi

App Service planını yapılandırmak için bu sayfayı görmüyorsanız öğreticiye devam edin. Uygulamayı daha sonra yayımlarken yapılandırabilirsiniz.

WebAPI arka ucunda istemcilerin kimliğini doğrulama

Bu bölümde, yeni arka uç için AuthenticationTestHandler adlı yeni bir ileti işleyicisi oluşturacaksınız. Bu sınıf DelegatingHandler’dan türetilip bir ileti işleyicisi olarak eklenir, böylece arka uca gelen tüm istekleri işleyebilir.

  1. Çözüm Gezgini'nde AppBackend projesine sağ tıklayın, Ekle'yi ve ardından Sınıf'ı seçin.

  2. Yeni AuthenticationTestHandler.cs sınıfını adlandırıp Ekle’yi seçerek sınıfı oluşturun. Bu sınıf, kolaylık için Temel Kimlik Doğrulaması kullanarak kullanıcıların kimliklerini doğrular. Uygulamanız herhangi bir kimlik doğrulama şemasını kullanabilir.

  3. AuthenticationTestHandler.cs sınıfına aşağıdaki using deyimlerini ekleyin:

    using System.Net.Http;
    using System.Threading;
    using System.Security.Principal;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
  4. AuthenticationTestHandler.cs sınıfında AuthenticationTestHandler sınıf tanımını aşağıdaki kod ile değiştirin:

    Bu işleyici aşağıdaki üç koşul geçerli olduğunda bu isteği yetkilendirir:

    • İstek bir Yetkilendirme üst bilgisi içerir.
    • İstek temel kimlik doğrulaması kullanır.
    • Kullanıcı adı dizesi ve parola dizesi aynı dizelerdir.

    Aksi takdirde istek reddedilir. Bu kimlik doğrulama işlemi, geçerli bir kimlik doğrulama ve yetkilendirme yaklaşımı değildir. Yalnızca bu öğreticiye yönelik basit bir örnektir.

    İstek iletisi AuthenticationTestHandler tarafından kimlik doğrulaması yapılır ve yetkilendirilirse, temel kimlik doğrulaması kullanıcısı HttpContext üzerindeki geçerli isteğe eklenir. HttpContext içindeki kullanıcı bilgileri, bildirim kaydı isteğine bir etiket eklemek amacıyla daha sonra başka bir denetleyici (RegisterController) tarafından kullanılır.

    public class AuthenticationTestHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var authorizationHeader = request.Headers.GetValues("Authorization").First();
    
            if (authorizationHeader != null && authorizationHeader
                .StartsWith("Basic ", StringComparison.InvariantCultureIgnoreCase))
            {
                string authorizationUserAndPwdBase64 =
                    authorizationHeader.Substring("Basic ".Length);
                string authorizationUserAndPwd = Encoding.Default
                    .GetString(Convert.FromBase64String(authorizationUserAndPwdBase64));
                string user = authorizationUserAndPwd.Split(':')[0];
                string password = authorizationUserAndPwd.Split(':')[1];
    
                if (VerifyUserAndPwd(user, password))
                {
                    // Attach the new principal object to the current HttpContext object
                    HttpContext.Current.User =
                        new GenericPrincipal(new GenericIdentity(user), new string[0]);
                    System.Threading.Thread.CurrentPrincipal =
                        System.Web.HttpContext.Current.User;
                }
                else return Unauthorized();
            }
            else return Unauthorized();
    
            return base.SendAsync(request, cancellationToken);
        }
    
        private bool VerifyUserAndPwd(string user, string password)
        {
            // This is not a real authentication scheme.
            return user == password;
        }
    
        private Task<HttpResponseMessage> Unauthorized()
        {
            var response = new HttpResponseMessage(HttpStatusCode.Forbidden);
            var tsc = new TaskCompletionSource<HttpResponseMessage>();
            tsc.SetResult(response);
            return tsc.Task;
        }
    }
    

    Not

    Güvenlik notu: AuthenticationTestHandler sınıfı gerçek kimlik doğrulaması sağlamaz. Yalnızca temel kimlik doğrulamasını taklit etmek için kullanılır ve güvenli değildir. Üretim uygulamalarınızda ve hizmetlerinizde güvenli bir kimlik doğrulama mekanizması uygulamanız gerekir.

  5. İleti işleyicisini kaydetmek için Program.cs dosyasında yönteminin Register sonuna aşağıdaki kodu ekleyin:

    config.MessageHandlers.Add(new AuthenticationTestHandler());
    
  6. Yaptığınız değişiklikleri kaydedin.

WebAPI arka ucunu kullanarak bildirimlere kaydolma

Bu bölümde, bildirim hub’ları için istemci kitaplığını kullanarak WebAPI arka ucuna bir kullanıcı ve cihazı bildirimlere kaydetme isteklerini işlemek üzere yeni bir denetleyici ekleyeceksiniz. Denetleyici, kimliği doğrulanmış ve AuthenticationTestHandler tarafından HttpContext’e eklenmiş kullanıcı için bir kullanıcı etiketi ekler. Etiket "username:<actual username>" dize biçiminde olacaktır.

  1. Çözüm Gezgini'nde, AppBackend projesine sağ tıklayın ve ardından NuGet Paketlerini Yönet'i seçin.

  2. Sol bölmede Çevrimiçi’ni seçin ve Arama kutusuna Microsoft.Azure.NotificationHubs yazın.

  3. Sonuç listesinde Microsoft Azure Notification Hubs’ı ve ardından Yükle’yi seçin. Yüklemeyi tamamlayın ve sonra NuGet Paket Yöneticisi penceresini kapatın.

    Bu eylem Microsoft.Azure.Notification Hubs NuGet paketini kullanarak Azure Notification Hubs SDK'sına bir başvuru ekler.

  4. Bildirimleri göndermek için kullanılan bildirim hub'ı bağlantısını temsil eden yeni bir sınıf dosyası oluşturun. Çözüm Gezgini'nde Modeller klasörüne sağ tıklayın, Ekle'yi ve ardından Sınıf'ı seçin. Yeni sınıfı Notifications.cs olarak adlandırın, ardından Ekle’yi seçerek sınıfı oluşturun.

    Yeni Öğe Ekle penceresi

  5. Notifications.cs sınıfında aşağıdaki using deyimini dosyanın üst kısmına ekleyin:

    using Microsoft.Azure.NotificationHubs;
    
  6. Notifications sınıf tanımını aşağıdaki kodla değiştirin ve iki yer tutucuyu bildirim hub’ınızın bağlantı dizesi (tam erişimli) ve hub adı ile değiştirdiğinizden emin olun (Azure portalında bulunabilir):

    public class Notifications
    {
        public static Notifications Instance = new Notifications();
    
        public NotificationHubClient Hub { get; set; }
    
        private Notifications() {
            Hub = NotificationHubClient.CreateClientFromConnectionString("<your hub's DefaultFullSharedAccessSignature>",
                                                                            "<hub name>");
        }
    }
    

    Önemli

    Devam etmeden önce hub'ınızın adını ve DefaultFullSharedAccessSignature değerini girin.

  7. Ardından RegisterController adlı yeni bir denetleyici oluşturun. Çözüm Gezgini'nde Denetleyiciler klasörüne sağ tıklayın, Ekle'yi ve ardından Denetleyici'yi seçin.

  8. API Denetleyicisi - Boş'u ve ardından Ekle'yi seçin.

  9. Denetleyici adı kutusuna, yeni sınıfı adlandırmak için RegisterController yazın ve Ekle’yi seçin.

    Denetleyici Ekle penceresi.

  10. RegisterController.cs sınıfına aşağıdaki using deyimlerini ekleyin:

    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.NotificationHubs.Messaging;
    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  11. Aşağıdaki kodu RegisterController sınıf tanımına ekleyin. Bu kodda, HttpContext’e eklenen kullanıcı için bir kullanıcı etiketi eklersiniz. Kullanıcının kimliği doğrulanmış ve eklediğiniz AuthenticationTestHandler ileti filtresi tarafından HttpContext’e eklenmiştir. Ayrıca, kullanıcının istenen etiketlere kaydolma haklarının olduğunu doğrulamak için isteğe bağlı denetimler ekleyebilirsiniz.

    private NotificationHubClient hub;
    
    public RegisterController()
    {
        hub = Notifications.Instance.Hub;
    }
    
    public class DeviceRegistration
    {
        public string Platform { get; set; }
        public string Handle { get; set; }
        public string[] Tags { get; set; }
    }
    
    // POST api/register
    // This creates a registration id
    public async Task<string> Post(string handle = null)
    {
        string newRegistrationId = null;
    
        // make sure there are no existing registrations for this push handle (used for iOS and Android)
        if (handle != null)
        {
            var registrations = await hub.GetRegistrationsByChannelAsync(handle, 100);
    
            foreach (RegistrationDescription registration in registrations)
            {
                if (newRegistrationId == null)
                {
                    newRegistrationId = registration.RegistrationId;
                }
                else
                {
                    await hub.DeleteRegistrationAsync(registration);
                }
            }
        }
    
        if (newRegistrationId == null) 
            newRegistrationId = await hub.CreateRegistrationIdAsync();
    
        return newRegistrationId;
    }
    
    // PUT api/register/5
    // This creates or updates a registration (with provided channelURI) at the specified id
    public async Task<HttpResponseMessage> Put(string id, DeviceRegistration deviceUpdate)
    {
        RegistrationDescription registration = null;
        switch (deviceUpdate.Platform)
        {
            case "mpns":
                registration = new MpnsRegistrationDescription(deviceUpdate.Handle);
                break;
            case "wns":
                registration = new WindowsRegistrationDescription(deviceUpdate.Handle);
                break;
            case "apns":
                registration = new AppleRegistrationDescription(deviceUpdate.Handle);
                break;
            case "fcm":
                registration = new FcmRegistrationDescription(deviceUpdate.Handle);
                break;
            default:
                throw new HttpResponseException(HttpStatusCode.BadRequest);
        }
    
        registration.RegistrationId = id;
        var username = HttpContext.Current.User.Identity.Name;
    
        // add check if user is allowed to add these tags
        registration.Tags = new HashSet<string>(deviceUpdate.Tags);
        registration.Tags.Add("username:" + username);
    
        try
        {
            await hub.CreateOrUpdateRegistrationAsync(registration);
        }
        catch (MessagingException e)
        {
            ReturnGoneIfHubResponseIsGone(e);
        }
    
        return Request.CreateResponse(HttpStatusCode.OK);
    }
    
    // DELETE api/register/5
    public async Task<HttpResponseMessage> Delete(string id)
    {
        await hub.DeleteRegistrationAsync(id);
        return Request.CreateResponse(HttpStatusCode.OK);
    }
    
    private static void ReturnGoneIfHubResponseIsGone(MessagingException e)
    {
        var webex = e.InnerException as WebException;
        if (webex.Status == WebExceptionStatus.ProtocolError)
        {
            var response = (HttpWebResponse)webex.Response;
            if (response.StatusCode == HttpStatusCode.Gone)
                throw new HttpRequestException(HttpStatusCode.Gone.ToString());
        }
    }
    
  12. Yaptığınız değişiklikleri kaydedin.

WebAPI arka ucundan bildirim gönderme

Bu bölümde, istemci cihazlarına bildirim göndermeleri için bir yol sunan yeni bir denetleyici ekleyeceksiniz. Bildirim, ASP.NET WebAPI arka ucundaki Azure Notification Hubs .NET Kitaplığı’nı kullanan kullanıcı adı etiketini temel alır.

  1. Önceki bölümde RegisterController denetleyicisini oluşturduğunuz gibi NotificationsController adlı yeni bir denetleyici oluşturun.

  2. NotificationsController.cs sınıfına aşağıdaki using deyimlerini ekleyin:

    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  3. Aşağıdaki yöntemi NotificationsController sınıfına ekleyin:

    Bu kod, Platform Bildirim Hizmeti (PNS) pns parametresini temel alan bir bildirim türü gönderir. to_tag değeri, iletideki kullanıcı adı etiketini ayarlamak için kullanılır. Bu etiket, etkin bir bildirim hub'ı kaydının kullanıcı etiketi ile eşleşmelidir. Bildirim iletisi, POST isteğinin gövdesinden çekilir ve hedef PNS biçimlendirilir.

    Desteklenen cihazlarınızın bildirimleri almak için kullandığı PNS’e bağlı olarak, bildirimler çeşitli biçimler tarafından desteklenmektedir. Örneğin, Windows cihazlarında başka bir PNS tarafından doğrudan desteklenmeyen bir WNS ile bildirim kullanabilirsiniz. Böyle bir durumda arka ucunuzun, desteklemeyi planladığınız cihazların PNS’si için bildirimi desteklenen bir bildirim biçimine dönüştürmesi gerekir. Daha sonra NotificationHubClient sınıfında uygun gönderme API’sini kullanın.

    public async Task<HttpResponseMessage> Post(string pns, [FromBody]string message, string to_tag)
    {
        var user = HttpContext.Current.User.Identity.Name;
        string[] userTag = new string[2];
        userTag[0] = "username:" + to_tag;
        userTag[1] = "from:" + user;
    
        Microsoft.Azure.NotificationHubs.NotificationOutcome outcome = null;
        HttpStatusCode ret = HttpStatusCode.InternalServerError;
    
        switch (pns.ToLower())
        {
            case "wns":
                // Windows 8.1 / Windows Phone 8.1
                var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">" + 
                            "From " + user + ": " + message + "</text></binding></visual></toast>";
                outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag);
                break;
            case "apns":
                // iOS
                var alert = "{\"aps\":{\"alert\":\"" + "From " + user + ": " + message + "\"}}";
                outcome = await Notifications.Instance.Hub.SendAppleNativeNotificationAsync(alert, userTag);
                break;
            case "fcm":
                // Android
                var notif = "{ \"data\" : {\"message\":\"" + "From " + user + ": " + message + "\"}}";
                outcome = await Notifications.Instance.Hub.SendFcmNativeNotificationAsync(notif, userTag);
                break;
        }
    
        if (outcome != null)
        {
            if (!((outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Abandoned) ||
                (outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Unknown)))
            {
                ret = HttpStatusCode.OK;
            }
        }
    
        return Request.CreateResponse(ret);
    }
    
  4. Uygulamayı çalıştırmak ve o ana kadar gerçekleştirdiğiniz işin doğruluğundan emin olmak için F5 tuşuna basın. Uygulama bir web tarayıcısı açar ve ASP.NET giriş sayfasında görüntülenir.

Yeni WebAPI arka ucunu yayımlama

Ardından bu uygulamayı tüm cihazlardan erişilebilir kılmak için bir Azure web sitesine dağıtacaksınız.

  1. AppBackend projesine sağ tıklayıp Yayımla’yı seçin.

  2. Yayımlama hedefi olarak Microsoft Azure App Service’i ve ardından \*\*Yayımla’yı seçin. App Service Oluştur penceresi açılır. Burada, Azure’da ASP.NET web uygulamasını çalıştırmak için gereken tüm Azure kaynaklarını oluşturabilirsiniz.

    Microsoft Azure App Service kutucuğu

  3. App Service Oluştur penceresinde Azure hesabınızı seçin. Tür>Web Uygulamasını Değiştir'i seçin. Varsayılan Web App Adı’nı değiştirmeyin ve Abonelik, Kaynak Grubu ve App Service Planı’nı seçin.

  4. Oluştur’u seçin.

  5. Özet bölümündeki Site URL özelliğini not edin. Bu URL, daha sonra bu öğreticide arka uca ait uç noktanız olacaktır.

  6. Yayımla’yı seçin.

Sihirbazı tamamladıktan sonra ASP.NET web uygulamasını Azure’da yayımlar ve ardından uygulamayı varsayılan tarayıcıda açar. Uygulamanız Azure App Services’te görüntülenebilir.

URL, daha önce belirttiğiniz web uygulaması adını http://< app_name.azurewebsites.net> biçiminde kullanır.

iOS uygulamanızı değiştirme

  1. Azure Notification Hubs kullanarak iOS uygulamalarına anında iletme bildirimleri gönderme öğreticisinde oluşturduğunuz Tek Sayfa görünümü uygulamasını açın.

    Not

    Bu bölümde, projenizin boş bir kuruluş adıyla yapılandırıldığı varsayılır. Aksi takdirde, kuruluşunuzun adını tüm sınıf adlarına ekleyin.

  2. Main.storyboard dosyasında, nesne kitaplığındaki ekran görüntüsünde gösterilen bileşenleri ekleyin.

    Xcode arabirim oluşturucusunda görsel taslak düzenleme

    • Kullanıcı adı: Yer tutucu metin içeren bir UITextField, Sonuç gönderme etiketinin hemen altında ve sol ve sağ kenar boşluklarına ve sonuçları gönderme etiketinin altına kısıtlanmış Kullanıcı Adı girin.

    • Parola: Kullanıcı adı metin alanının hemen altında, sol ve sağ kenar boşluklarına ve kullanıcı adı metin alanının altına kısıtlanmış, yer tutucu metin içeren Bir UITextField , Parola Girin. Öznitelik Denetçisi'nde, Dönüş Anahtarı'nın altındaki Güvenli Metin Girişi seçeneğini işaretleyin.

    • Oturum açın: Parola metin alanının hemen altında etiketlenmiş bir UIButton düğmesi ve Control-Content altındaki Öznitelikler Denetçisi'nde Etkin seçeneğinin işaretini kaldırın

    • WNS: Hub'da ayarlandıysa bildirim Windows Bildirim Hizmeti'ni göndermeyi etkinleştirin ve etkinleştirin. Bkz. Windows Kullanmaya Başlama öğreticisi.

    • GCM: Hub'da ayarlanmışsa, bildirimi Google Cloud Messaging'e göndermeyi etiketleyin ve etkinleştirin. Bkz. Android Kullanmaya Başlama öğreticisi.

    • APNS: Apple Platform Bildirim Hizmeti'ne bildirim göndermeyi etkinleştirmek için etiketleyip geçiş yapın.

    • Alıcı Kullanıcı Adı: Yer tutucu metin içeren bir UITextField, GcM etiketinin hemen altında, sol ve sağ kenar boşluklarıyla GCM etiketinin altında kısıtlanmış Alıcı kullanıcı adı etiketi.

      Azure Notification Hubs kullanarak iOS uygulamalarına anında iletme bildirimleri gönderme öğreticisine bazı bileşenler eklendi.

  3. Ctrl tuşunu basılı tutarak görünümdeki ViewController.h bileşenlerden şu yeni çıkışları ekleyin:

    @property (weak, nonatomic) IBOutlet UITextField *UsernameField;
    @property (weak, nonatomic) IBOutlet UITextField *PasswordField;
    @property (weak, nonatomic) IBOutlet UITextField *RecipientField;
    @property (weak, nonatomic) IBOutlet UITextField *NotificationField;
    
    // Used to enable the buttons on the UI
    @property (weak, nonatomic) IBOutlet UIButton *LogInButton;
    @property (weak, nonatomic) IBOutlet UIButton *SendNotificationButton;
    
    // Used to enabled sending notifications across platforms
    @property (weak, nonatomic) IBOutlet UISwitch *WNSSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *GCMSwitch;
    @property (weak, nonatomic) IBOutlet UISwitch *APNSSwitch;
    
    - (IBAction)LogInAction:(id)sender;
    
  4. içinde ViewController.h, içeri aktarma deyimlerinizden sonra aşağıdakileri #define ekleyin. Yer tutucuyu <Your backend endpoint> , önceki bölümde uygulamanızın arka ucu dağıtmak için kullandığınız Hedef URL ile değiştirin. Örneğin, http://your_backend.azurewebsites.net:

    #define BACKEND_ENDPOINT @"<Your backend endpoint>"
    
  5. Projenizde oluşturduğunuz ASP.NET arka ucuyla arabirim oluşturmak için adlı RegisterClient yeni bir Cocoa Touch sınıfı oluşturun. öğesinden NSObjectdevralan sınıfı oluşturun. Ardından içine aşağıdaki kodu RegisterClient.hekleyin:

    @interface RegisterClient : NSObject
    
    @property (strong, nonatomic) NSString* authenticationHeader;
    
    -(void) registerWithDeviceToken:(NSData*)token tags:(NSSet*)tags
        andCompletion:(void(^)(NSError*))completion;
    
    -(instancetype) initWithEndpoint:(NSString*)Endpoint;
    
    @end
    
  6. içinde RegisterClient.mbölümünü güncelleştirin @interface :

    @interface RegisterClient ()
    
    @property (strong, nonatomic) NSURLSession* session;
    @property (strong, nonatomic) NSURLSession* endpoint;
    
    -(void) tryToRegisterWithDeviceToken:(NSData*)token tags:(NSSet*)tags retry:(BOOL)retry
                andCompletion:(void(^)(NSError*))completion;
    -(void) retrieveOrRequestRegistrationIdWithDeviceToken:(NSString*)token
                completion:(void(^)(NSString*, NSError*))completion;
    -(void) upsertRegistrationWithRegistrationId:(NSString*)registrationId deviceToken:(NSString*)token
                tags:(NSSet*)tags andCompletion:(void(^)(NSURLResponse*, NSError*))completion;
    
    @end
    
  7. @implementation RegisterClient.m dosyasındaki bölümünü aşağıdaki kodla değiştirin:

    @implementation RegisterClient
    
    // Globals used by RegisterClient
    NSString *const RegistrationIdLocalStorageKey = @"RegistrationId";
    
    -(instancetype) initWithEndpoint:(NSString*)Endpoint
    {
        self = [super init];
        if (self) {
            NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
            _session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:nil];
            _endpoint = Endpoint;
        }
        return self;
    }
    
    -(void) registerWithDeviceToken:(NSData*)token tags:(NSSet*)tags
                andCompletion:(void(^)(NSError*))completion
    {
        [self tryToRegisterWithDeviceToken:token tags:tags retry:YES andCompletion:completion];
    }
    
    -(void) tryToRegisterWithDeviceToken:(NSData*)token tags:(NSSet*)tags retry:(BOOL)retry
                andCompletion:(void(^)(NSError*))completion
    {
        NSSet* tagsSet = tags?tags:[[NSSet alloc] init];
    
        NSString *deviceTokenString = [[token description]
            stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
        deviceTokenString = [[deviceTokenString stringByReplacingOccurrencesOfString:@" " withString:@""]
                                uppercaseString];
    
        [self retrieveOrRequestRegistrationIdWithDeviceToken: deviceTokenString
            completion:^(NSString* registrationId, NSError *error) {
            NSLog(@"regId: %@", registrationId);
            if (error) {
                completion(error);
                return;
            }
    
            [self upsertRegistrationWithRegistrationId:registrationId deviceToken:deviceTokenString
                tags:tagsSet andCompletion:^(NSURLResponse * response, NSError *error) {
                if (error) {
                    completion(error);
                    return;
                }
    
                NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
                if (httpResponse.statusCode == 200) {
                    completion(nil);
                } else if (httpResponse.statusCode == 410 && retry) {
                    [self tryToRegisterWithDeviceToken:token tags:tags retry:NO andCompletion:completion];
                } else {
                    NSLog(@"Registration error with response status: %ld", (long)httpResponse.statusCode);
    
                    completion([NSError errorWithDomain:@"Registration" code:httpResponse.statusCode
                                userInfo:nil]);
                }
    
            }];
        }];
    }
    
    -(void) upsertRegistrationWithRegistrationId:(NSString*)registrationId deviceToken:(NSData*)token
                tags:(NSSet*)tags andCompletion:(void(^)(NSURLResponse*, NSError*))completion
    {
        NSDictionary* deviceRegistration = @{@"Platform" : @"apns", @"Handle": token,
                                                @"Tags": [tags allObjects]};
        NSData* jsonData = [NSJSONSerialization dataWithJSONObject:deviceRegistration
                            options:NSJSONWritingPrettyPrinted error:nil];
    
        NSLog(@"JSON registration: %@", [[NSString alloc] initWithData:jsonData
                                            encoding:NSUTF8StringEncoding]);
    
        NSString* endpoint = [NSString stringWithFormat:@"%@/api/register/%@", _endpoint,
                                registrationId];
        NSURL* requestURL = [NSURL URLWithString:endpoint];
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL];
        [request setHTTPMethod:@"PUT"];
        [request setHTTPBody:jsonData];
        NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@",
                                                self.authenticationHeader];
        [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
        [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    
        NSURLSessionDataTask* dataTask = [self.session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
        {
            if (!error)
            {
                completion(response, error);
            }
            else
            {
                NSLog(@"Error request: %@", error);
                completion(nil, error);
            }
        }];
        [dataTask resume];
    }
    
    -(void) retrieveOrRequestRegistrationIdWithDeviceToken:(NSString*)token
                completion:(void(^)(NSString*, NSError*))completion
    {
        NSString* registrationId = [[NSUserDefaults standardUserDefaults]
                                    objectForKey:RegistrationIdLocalStorageKey];
    
        if (registrationId)
        {
            completion(registrationId, nil);
            return;
        }
    
        // request new one & save
        NSURL* requestURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/api/register?handle=%@",
                                _endpoint, token]];
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL];
        [request setHTTPMethod:@"POST"];
        NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@",
                                                self.authenticationHeader];
        [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
    
        NSURLSessionDataTask* dataTask = [self.session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
        {
            NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
            if (!error && httpResponse.statusCode == 200)
            {
                NSString* registrationId = [[NSString alloc] initWithData:data
                    encoding:NSUTF8StringEncoding];
    
                // remove quotes
                registrationId = [registrationId substringWithRange:NSMakeRange(1,
                                    [registrationId length]-2)];
    
                [[NSUserDefaults standardUserDefaults] setObject:registrationId
                    forKey:RegistrationIdLocalStorageKey];
                [[NSUserDefaults standardUserDefaults] synchronize];
    
                completion(registrationId, nil);
            }
            else
            {
                NSLog(@"Error status: %ld, request: %@", (long)httpResponse.statusCode, error);
                if (error)
                    completion(nil, error);
                else {
                    completion(nil, [NSError errorWithDomain:@"Registration" code:httpResponse.statusCode
                                userInfo:nil]);
                }
            }
        }];
        [dataTask resume];
    }
    
    @end
    

    Bu kod, uygulamanızın arka ucuna REST çağrıları gerçekleştirmek için NSURLSession kullanarak uygulama arka ucunuzdan kaydolma ve bildirim hub'ı tarafından döndürülen registrationId değerini yerel olarak depolamak için NSUserDefaults kılavuz makalesinde açıklanan mantığı uygular.

    Bu sınıf, düzgün çalışması için özelliğinin authorizationHeader ayarlanmasını gerektirir. Bu özellik, oturum açmadan ViewController sonra sınıfı tarafından ayarlanır.

  8. içinde ViewController.hiçin bir #import deyimi RegisterClient.hekleyin. Ardından cihaz belirteci için bir bildirim ve bölümünde bir RegisterClient örneğe @interface başvuru ekleyin:

    #import "RegisterClient.h"
    
    @property (strong, nonatomic) NSData* deviceToken;
    @property (strong, nonatomic) RegisterClient* registerClient;
    
  9. ViewController.m'de @interface bölümüne bir özel yöntem bildirimi ekleyin:

    @interface ViewController () <UITextFieldDelegate, NSURLConnectionDataDelegate, NSXMLParserDelegate>
    
    // create the Authorization header to perform Basic authentication with your app back-end
    -(void) createAndSetAuthenticationHeaderWithUsername:(NSString*)username
                    AndPassword:(NSString*)password;
    
    @end
    

    Not

    Aşağıdaki kod parçacığı güvenli bir kimlik doğrulama şeması değildir; uygulamasını createAndSetAuthenticationHeaderWithUsername:AndPassword: , yazmaç istemci sınıfı tarafından kullanılacak bir kimlik doğrulama belirteci oluşturan özel kimlik doğrulama mekanizmanızla (örneğin, OAuth, Active Directory) değiştirmelisiniz.

  10. @implementation Ardından bölümünde, cihaz belirtecini ViewController.mve kimlik doğrulama üst bilgisini ayarlamak için uygulamayı ekleyen aşağıdaki kodu ekleyin.

    -(void) setDeviceToken: (NSData*) deviceToken
    {
        _deviceToken = deviceToken;
        self.LogInButton.enabled = YES;
    }
    
    -(void) createAndSetAuthenticationHeaderWithUsername:(NSString*)username
                    AndPassword:(NSString*)password;
    {
        NSString* headerValue = [NSString stringWithFormat:@"%@:%@", username, password];
    
        NSData* encodedData = [[headerValue dataUsingEncoding:NSUTF8StringEncoding] base64EncodedDataWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
    
        self.registerClient.authenticationHeader = [[NSString alloc] initWithData:encodedData
                                                    encoding:NSUTF8StringEncoding];
    }
    
    -(BOOL)textFieldShouldReturn:(UITextField *)textField
    {
        [textField resignFirstResponder];
        return YES;
    }
    

    Cihaz belirtecinin ayarlanmasının Oturum aç düğmesini nasıl etkinleştirenlere dikkat edin. Bunun nedeni, oturum açma eyleminin bir parçası olarak görünüm denetleyicisinin uygulama arka ucuyla anında iletme bildirimlerine kaydolmasıdır. Cihaz belirteci düzgün şekilde ayarlanana kadar Oturum açma eyleminin erişilebilir olmasını istemezsiniz. Önceki kayıttan önce olduğu sürece, giriş bilgilerini anında iletme kaydından ayrıştırabilirsiniz.

  11. ViewController.m'de, Oturum aç düğmenizin eylem yöntemini uygulamak için aşağıdaki kod parçacıklarını ve ASP.NET arka ucu kullanarak bildirim iletisini gönderme yöntemini kullanın.

    - (IBAction)LogInAction:(id)sender {
        // create authentication header and set it in register client
        NSString* username = self.UsernameField.text;
        NSString* password = self.PasswordField.text;
    
        [self createAndSetAuthenticationHeaderWithUsername:username AndPassword:password];
    
        __weak ViewController* selfie = self;
        [self.registerClient registerWithDeviceToken:self.deviceToken tags:nil
            andCompletion:^(NSError* error) {
            if (!error) {
                dispatch_async(dispatch_get_main_queue(),
                ^{
                    selfie.SendNotificationButton.enabled = YES;
                    [self MessageBox:@"Success" message:@"Registered successfully!"];
                });
            }
        }];
    }
    
    - (void)SendNotificationASPNETBackend:(NSString*)pns UsernameTag:(NSString*)usernameTag
                Message:(NSString*)message
    {
        NSURLSession* session = [NSURLSession
            sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:nil
            delegateQueue:nil];
    
        // Pass the pns and username tag as parameters with the REST URL to the ASP.NET backend
        NSURL* requestURL = [NSURL URLWithString:[NSString
            stringWithFormat:@"%@/api/notifications?pns=%@&to_tag=%@", BACKEND_ENDPOINT, pns,
            usernameTag]];
    
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL];
        [request setHTTPMethod:@"POST"];
    
        // Get the mock authenticationheader from the register client
        NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@",
            self.registerClient.authenticationHeader];
        [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
    
        //Add the notification message body
        [request setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [request setHTTPBody:[message dataUsingEncoding:NSUTF8StringEncoding]];
    
        // Execute the send notification REST API on the ASP.NET Backend
        NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
        {
            NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
            if (error || httpResponse.statusCode != 200)
            {
                NSString* status = [NSString stringWithFormat:@"Error Status for %@: %d\nError: %@\n",
                                    pns, httpResponse.statusCode, error];
                dispatch_async(dispatch_get_main_queue(),
                ^{
                    // Append text because all 3 PNS calls may also have information to view
                    [self.sendResults setText:[self.sendResults.text stringByAppendingString:status]];
                });
                NSLog(status);
            }
    
            if (data != NULL)
            {
                xmlParser = [[NSXMLParser alloc] initWithData:data];
                [xmlParser setDelegate:self];
                [xmlParser parse];
            }
        }];
        [dataTask resume];
    }
    
  12. Bildirim Gönder düğmesinin eylemini, ASP.NET arka ucu kullanacak ve bir anahtar tarafından etkinleştirilen herhangi bir PNS'ye gönderecek şekilde güncelleştirin.

    - (IBAction)SendNotificationMessage:(id)sender
    {
        //[self SendNotificationRESTAPI];
        [self SendToEnabledPlatforms];
    }
    
    -(void)SendToEnabledPlatforms
    {
        NSString* json = [NSString stringWithFormat:@"\"%@\"",self.notificationMessage.text];
    
        [self.sendResults setText:@""];
    
        if ([self.WNSSwitch isOn])
            [self SendNotificationASPNETBackend:@"wns" UsernameTag:self.RecipientField.text Message:json];
    
        if ([self.GCMSwitch isOn])
            [self SendNotificationASPNETBackend:@"gcm" UsernameTag:self.RecipientField.text Message:json];
    
        if ([self.APNSSwitch isOn])
            [self SendNotificationASPNETBackend:@"apns" UsernameTag:self.RecipientField.text Message:json];
    }
    
  13. işlevinde ViewDidLoad örneği başlatmak RegisterClient ve metin alanlarınız için temsilciyi ayarlamak için aşağıdakileri ekleyin.

    self.UsernameField.delegate = self;
    self.PasswordField.delegate = self;
    self.RecipientField.delegate = self;
    self.registerClient = [[RegisterClient alloc] initWithEndpoint:BACKEND_ENDPOINT];
    
  14. Şimdi içinde AppDelegate.myönteminin application:didRegisterForPushNotificationWithDeviceToken: tüm içeriğini kaldırın ve şununla değiştirin (görünüm denetleyicisinin APN'lerden alınan en son cihaz belirtecini içerdiğinden emin olmak için):

    // Add import to the top of the file
    #import "ViewController.h"
    
    - (void)application:(UIApplication *)application
                didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    {
        ViewController* rvc = (ViewController*) self.window.rootViewController;
        rvc.deviceToken = deviceToken;
    }
    
  15. Son olarak içinde AppDelegate.maşağıdaki yönteme sahip olduğunuzdan emin olun:

    - (void)application:(UIApplication *)application didReceiveRemoteNotification: (NSDictionary *)userInfo {
        NSLog(@"%@", userInfo);
        [self MessageBox:@"Notification" message:[[userInfo objectForKey:@"aps"] valueForKey:@"alert"]];
    }
    

Uygulamayı test edin

  1. XCode'da uygulamayı fiziksel bir iOS cihazında çalıştırın (anında iletme bildirimleri simülatörde çalışmaz).

  2. iOS uygulama kullanıcı arabiriminde hem kullanıcı adı hem de parola için aynı değeri girin. Ardından Oturum aç'a tıklayın.

    iOS test uygulaması

  3. Kayıt başarısı konusunda sizi bilgilendiren bir açılır pencere görmeniz gerekir. Tamam'a tıklayın.

    iOS test bildirimi görüntüleniyor

  4. *Alıcı kullanıcı adı etiketi metin alanına, başka bir cihazdan kayıtta kullanılan kullanıcı adı etiketini girin.

  5. Bir bildirim iletisi girin ve Bildirim Gönder'e tıklayın. Yalnızca alıcı kullanıcı adı etiketiyle kaydı olan cihazlar bildirim iletisini alır. Yalnızca bu kullanıcılara gönderilir.

    iOS test etiketli bildirim

Sonraki adımlar

Bu öğreticide, kayıtlarıyla ilişkili etiketleri olan belirli kullanıcılara anında iletme bildirimleri göndermeyi öğrendiniz. Konum tabanlı anında iletme bildirimleri göndermeyi öğrenmek için aşağıdaki öğreticiye ilerleyin: