البرنامج التعليمي: إرسال إعلامات إلى مستخدمين محددين باستخدام Azure Notification Hubs

نظرة عامة

يصف هذا البرنامج التعليمي طريقة استخدام Azure Notification Hubs لإرسال إشعارات الدفع إلى مُستخدم محدَّد للتطبيق وإلى جهاز محدد. يتم استخدام خلفية WebAPI ASP.NET لمصادقة العملاء. عند مصادقة الخلفية مستخدم تطبيق عميل، يضيف تلقائيّاً علامة إلى تسجيل الإعلامات. تستخدم الخلفية هذه العلامة لإرسال إعلامات إلى مستخدم معين.

ملاحظة

يمكن العثور على التعليمة البرمجية المكتملة لهذا البرنامج التعليمي على GitHub.

في هذا البرنامج التعليمي، نُفذت الخطوات التالية:

  • إنشاء مشروع WebAPI
  • مصادقة العملاء في للخلفية WebAPI
  • التسجيل للحصول على الإشعارات باستخدام الخلفية WebAPI
  • إرسال الإشعارات من خلفية WebAPI
  • نشر الخلفية WebAPI الجديدة
  • تحديث التعليمة البرمجية لمشروع العميل
  • اختبر التطبيق

المتطلبات الأساسية

يقوم هذا البرنامج التعليمي على أساس مركز الإعلام وVisual Studio الذي أُنشئ في البرنامج التعليمي: إرسال الإشعارات إلى النظام الأساسي العام لـ Windows باستخدام البرنامج التعليمي Azure Notification Hubs. لذلك، أكمله قبل البدء في هذا البرنامج التعليمي.

ملاحظة

إذا كنت تستخدم تطبيقات الجوال في Azure App Service كخدمة خلفية، فشاهد لإصدار تطبيقات الجوال لدى بهذا البرنامج التعليمي.

إنشاء مشروع WebAPI

تناقش الفصول التالية إنشاء خلفية WebAPI ASP.NET جديدة. ولهذه العملية ثلاثة أغراض رئيسية:

  • مصادقة العملاء: يمكنك إضافة معالج رسالة لمصادقة طلبات العميل وإقران المستخدم مع الطلب.
  • التسجيل للحصول على إعلامات باستخدام واجهة برمجة تطبيقات الويب الخلفية: إضافة وحدة تحكم لمعالجة تسجيلات جديدة لجهاز عميل لتلقي الإشعارات. تتم إضافة اسم المستخدم المصادق عليه تلقائياً إلى التسجيل كعلامة.
  • إرسال إشعارات للعملاء: يمكنك إضافة وحدة تحكم لتوفير طريقة للمستخدمين لتشغيل دفعة آمنة للأجهزة والعملاء المقترنين بالعلامة.

أنشئ الواجهة الخلفية لواجهة برمجة تطبيقات الويب ASP.NET Core 6.0 الجديدة عن طريق القيام بالإجراءات التالية:

للتحقق، شغل Visual Studio. في قائمة "Tools" ، حدد "Extensions and Updates" . ابحث عن نسخة NuGet Package Manager من إصدار Visual Studio، وتأكد من حصولك على أحدث إصدار. إذا لم يكن الإصدار الخاص بك هو أحدث إصدار، فقم بإلغاء تثبيته، ثم أعد تثبيت NuGet Package Manager.

لقطة شاشة من مربع الحوار الامتدادات والتحديثات مع NuGet Package Manager لإدارة حزمة Visual Studios المظللة.

ملاحظة

تأكد من تثبيت Visual Studio Azure SDK لنشر موقع ويب.

  1. شغل Visual Studio أو Visual Studio Express.

  2. حدد "Server Explorer" ، ثم سجل الدخول إلى حساب Azure. لإنشاء موارد موقع ويب على حسابك، يجب تسجيل الدخول.

  3. في قائمة File في Visual Studio، حدد New>Project.

  4. أدخل Web API في مربع البحث.

  5. حدد قالب مشروع ASP.NET Core Web API وحدد Next.

  6. في مربع الحوار Configure your new project، قم بتسمية المشروع AppBackend وحدد Next.

  7. في مربع الحوار Additional information:

    • تأكد من أن Framework هو .NET 6.0 (دعم طويل الأجل).
    • تأكد من تحديد مربع الاختيار (قم بإلغاء تحديده لاستخدام الحد الأدنى من واجهات برمجة التطبيقات).
    • قم بإلغاء تحديد Enable OpenAPI support.
    • حدد Create.

قم بإزالة ملفات قالب WeatherForecast

  1. قم بإزالة نماذج ملفات WeatherForecast.cs وControllers/WeatherForecastController.cs من مشروع AppBackend الجديد.
  2. افتح Properties\launchSettings.json.
  3. غيّر خصائص launchUrl من weatherforcast إلى appbackend.

في نافذة Configure Microsoft Azure Web App، حدد اشتراك ثم في قائمة App Service plan، نفذ أي من الإجراءات التالية:

  • حدد خطة خدمة تطبيق Azure التي قمت بإنشائها بالفعل.
  • حدد Create a new app service plan ثم قم بإنشاء خطة.

لا تحتاج إلى قاعدة بيانات لهذا البرنامج التعليمي. بعد تحديد خطة خدمة التطبيق، حدد "OK" لإنشاء المشروع.

نافذة تكوين تطبيق ويب لـ Microsoft Azure

إذا لم تشاهد هذه الصفحة لتكوين خطة خدمة التطبيق، فتابع البرنامج التعليمي. يمكنك تكوينه أثناء نشر التطبيق لاحقاً.

مصادقة العملاء في واجهة برمجة تطبيقات الويب الخلفية

في هذا المقطع، يمكنك إنشاء فئة معالج رسالة جديدة تسمى AuthenticationTestHandler للواجهة الخلفية الجديدة. يتم اشتقاق هذه الفئة من DelegatingHandler وإضافتها كمعالج رسالة بحيث يمكن معالجة جميع الطلبات التي تأتي في الخلفية.

  1. في مستكشف الحلول، انقر بزر الماوس الأيمن فوق مشروع AppBackend، وحدد "Add" ، ثم حدد "Class" .

  2. اسم فئة جديدة AuthenticationTestHandler.cs، ثم حدد "Add" لإنشاء الفئة. هذه الفئة تصادق المستخدمين باستخدام المصادقة الأساسية للبساطة. يمكن للتطبيق استخدام أي نظام مصادقة.

  3. في AuthenticationTestHandler.cs، إضافة using العبارات التالية:

    using System.Net.Http;
    using System.Threading;
    using System.Security.Principal;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
  4. في AuthenticationTestHandler.cs استبدال تعريف AuthenticationTestHandler الفئة مع التعليمات البرمجية التالية:

    المعالج يسمح بالطلب عند تحقق الشروط الثلاثة التالية:

    • يتضمن الطلب عنوان ⁧التصريح.⁩
    • يستخدم الطلب المصادقة الأساسية.
    • سلسلة اسم المستخدم وسلسلة كلمة المرور هي نفس السلسلة.

    وإلا، يتم رفض الطلب. هذه المصادقة ليست مصادقة حقيقية ونهج التصريح. إنها مجرد مثال بسيط لهذا البرنامج التعليمي.

    إذا تمت مصادقة رسالة الطلب ومنح تصريح من قبل AuthenticationTestHandler، يتم إرفاق مستخدم المصادقة الأساسي بالطلب الحالي على HttpContext. سيتم استخدام معلومات المستخدم في HttpContext بواسطة وحدة تحكم أخرى (RegisterController) لاحقاً لإضافة طلب إلى طلب تسجيل الإخطار.

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

    ملاحظة

    ملاحظة الأمان: AuthenticationTestHandler لا توفر الفئة المصادقة الحقيقية. يتم استخدامه فقط لمحاكاة المصادقة الأساسية كما أنه غير آمن. يجب تطبيق آلية مصادقة آمنة في تطبيقات الإنتاج والخدمات.

  5. لتسجيل معالج الرسالة، أضف التعليمة البرمجية التالية في نهاية الطريقة Register في ملف Program.cs:

    config.MessageHandlers.Add(new AuthenticationTestHandler());
    
  6. حفظ التغييرات.

التسجيل للحصول على الإشعارات باستخدام واجهة برمجة تطبيقات الويب الخلفية

في هذا القسم، يمكنك إضافة وحدة تحكم جديدة إلى الواجهة الخلفية لواجهة برمجة تطبيقات الويب للتعامل مع طلبات تسجيل مستخدم وجهاز للإخطارات باستخدام مكتبة العميل لمراكز الإشعارات. تضيف وحدة التحكم علامة مستخدم للمستخدم الذي تمت مصادقته وتعلق عليه HttpContext بواسطة AuthenticationTestHandler. العلامة لها تنسيق السلسلة، "username:<actual username>".

  1. في مستكشف الحلول، انقر بزر الماوس الأيمن فوق مشروع AppBackend ثم حدد "Manage NuGet Packages" .

  2. في الجزء الأيمن، حدد "Online" ثم، في مربع "Search" ، اكتب Microsoft.Azure.NotificationHubs.

  3. في قائمة النتائج، حدد "Microsoft Azure Notification Hubs" ، ثم حدد "Install" . أكمل التثبيت، ثم أغلق نافذة NuGet Package Manager.

    يضيف هذا الإجراء مرجعاً إلى SDK مراكز إشعار Azure باستخدام حزمة Microsoft.Azure.Notification Hubs NuGet.

  4. إنشاء ملف فئة جديد يمثل الاتصال بمركز الإشعارات المستخدم لإرسال الإشعارات. في مستكشف الحلول، انقر بزر الماوس الأيمن فوق المجلد "Models" ، وحدد "Add" ، ثم حدد "Class" . اختر اسم الفئة الجديدة إشعارات.cs، ثم حدد "Add" لإنشاء الفئة.

    نافذة إضافة عنصر جديد

  5. في إشعارات.cs، أضف العبارة التالية using في أعلى الملف:

    using Microsoft.Azure.NotificationHubs;
    
  6. استبدال ⁧Notifications⁩ تعريف الفئة مع التعليمات البرمجية التالية، واستبدال العنصرين النائبين مع سلسلة الاتصال (مع الوصول الكامل) لمركز الإشعار واسم لوحة الوصل (متوفر في ⁧بوابة Azure⁩):⁧

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

    هام

    أدخل الاسم و DefaultFullSharedAccessSignature لوحة الوصل قبل المتابعة.

  7. بعد ذلك، إنشاء وحدة تحكم جديدة تسمى RegisterController. في مستكشف الحلول، انقر بزر الماوس الأيمن فوق المجلد وحدات التحكم، وحدد "Add" ، ثم حدد "Controller" .

  8. حدد API Controller - Empty، ثم حدد Add.

  9. في المربع "Controller name" اكتب RegisterController لتسمية الفئة الجديدة ثم حدد "Add" .

    نافذة إضافة وحدة تحكم.

  10. في سجلController.cs، إضافة using العبارات التالية:

    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.NotificationHubs.Messaging;
    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  11. إضافة التعليمات البرمجية التالية داخل RegisterController تعريف الفئة. في هذه التعليمة البرمجية، يمكنك إضافة علامة مستخدم للمستخدم المرفق بـ HttpContext. تمت مصادقة المستخدم وإرفاق HttpContext بواسطة عامل تصفية الرسالة التي قمت AuthenticationTestHandler بإضافتها. يمكنك أيضاً إضافة تدقيقات اختيارية للتحقق من أن المستخدم لديه حقوق التسجيل للعلامات المطلوبة.

    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. حفظ التغييرات.

إرسال إشعارات من الواجهة الخلفية لواجهة برمجة تطبيقات الويب

في هذا الفصل، يمكنك إضافة وحدة تحكم جديدة تعرض طريقة للأجهزة العميلة لإرسال إشعار. يستند الإشعار إلى علامة اسم المستخدم الذي يستخدم لوحة إشعارات Azure.NET مكتبة في الخلفية WebAPI ASP.NET.

  1. إنشاء وحدة تحكم جديدة أخرى تسمى NotificationsController بنفس الطريقة التي قمت بإنشائها RegisterController في المقطع السابق.

  2. في NotificationsController.cs، إضافة using العبارات التالية:

    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  3. إضافة الأسلوب التالي إلى NotificationsController الفئة:

    يرسل هذا الرمز نوع إشعار يستند إلى مؤشر خدمة إشعار المنصة pns. يتم استخدام قيمة to_tag لتعيين علامة اسم المستخدم على الرسالة. يجب أن تتطابق هذه العلامة مع علامة اسم مستخدم لتسجيل مركز إشعار نشط. يتم سحب رسالة الإعلام من نص طلب POST وتنسيقها لخدمة إشعار المنصة المستهدف.

    بناءً على خدمة إشعار المنصة التي تستخدمها الأجهزة المعتمدة لتلقي الإشعارات، يتم دعم الإشعارات بمجموعة متنوعة من التنسيقات. على سبيل المثال، على أجهزة الويندوز، قد تستخدم إشعاراً منبثقاً مع WNSغير معتمد مباشرة من قِبَل خدمة إشعار المنصة أخرى. في مثل هذه الحالة، تحتاج الخلفية لتنسيق الإشعار في إشعار معتمد لخدمة إشعار المنصة من الأجهزة التي تخطط لدعمها. ثم استخدم واجهة تطبيق البرامج للإرسال المناسب على الفئة NotificationHubClient class.

    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. لتشغيل التطبيق والتأكد من دقة عملك حتى الآن، اختر المفتاح ⁧⁩F5.⁧⁩ يفتح التطبيق متصفح ويب، ويتم عرضه على الصفحة الرئيسية ASP.NET.

نشر الخلفية WebAPI الجديدة

بعد ذلك، يمكنك نشر التطبيق على موقع Azure على الويب لجعله متاحاً من جميع الأجهزة.

  1. انقر بزر الماوس الأيمن فوق مشروع AppBackend، ثم حدد "Publish" .

  2. حدد "Microsoft Azure App Service" كهدف للنشر، ثم حدد نشر**. يتم فتح نافذة إنشاء خدمة التطبيقات. هنا يمكنك إنشاء جميع الموارد Azure اللازمة لتشغيل التطبيق ASP.NET ويب في Azure.

    لوحة خدمة تطبيقات Microsoft Azure

  3. في نافذة "Create App Service" ، حدد حساب Azure. حدد "Change Type">"Web App" . احتفظ باسم تطبيق ويبالافتراضي، ثم حدد "Subscription" ، و "Resource Group" ، و "App Service Plan" .

  4. حدد Create.

  5. دون ملاحظة عن خاصية URL للموقع في قسم الملخص. عنوان URL هذا هو نقطة النهاية الخلفية في وقت لاحق في البرنامج التعليمي.

  6. حدد نشر.

بعد الانتهاء من المعالج، فإنه ينشر تطبيق الويب ASP.NET إلى Azure ثم يفتح التطبيق في المستعرض الافتراضي. تطبيقك قابل للعرض في خدمات تطبيقات Azure.

يستخدم عنوان URL اسم تطبيق الويب الذي حددته مسبقاً، بالتنسيق http://<app_name>.azurewebsites.net.

تحديث التعليمة البرمجية لعميل UWP

في هذا القسم، يمكنك تحديث التعليمة البرمجية في المشروع الذي أكملته للبرنامج التعليمي : إرسال إعلامات إلى تطبيقات النظام الأساسي العام لـ Windows باستخدام البرنامج التعليمي Azure Notification Hubs. يجب أن يكون المشروع مقترناً بالفعل بمتجر Windows. كما يجب تكوينه لاستخدام لوحة مركز الإعلام. في هذا القسم، يمكنك إضافة تعليمات برمجية لاستدعاء الخلفية WebAPI الجديدة واستخدامها لتسجيل الإعلامات وإرسالها.

  1. في Visual Studio، افتح الحل الذي أنشأته للبرنامج التعليمي : إرسال إعلامات إلى تطبيقات النظام الأساسي العالمي من Windows باستخدام Azure Notification Hubs.

  2. في مستكشف الحلول، انقر بزر الماوس الأيمن فوق مشروع النظام الأساسي العام لـ Windows (UWP) ثم انقر فوق Manage NuGet Packages.

  3. على الجانب الأيسر، حدد Browse.

  4. في مربع Search، اكتب Http Client.

  5. في قائمة النتائج، انقر System.Net.Http، وانقر Install. أكمل التثبيت.

  6. مرة أخرى في مربع Search NuGet، اكتب Json.net. تثبيت حزمة Newtonsoft.json، ثم قم بإغلاق إطار إدارة حِزَم NuGet.

  7. في مستكشف الحلول، في مشروع WindowsApp، انقر نقراً مزدوجاً فوق MainPage.xaml لفتحه في محرر Visual Studio.

  8. في ملف MainPage.xaml، استبدل القسم <Grid> بالتعليمة البرمجية التالية: تضيف هذه التعليمة البرمجية مربع نص اسم مستخدم وكلمة مرور يصادق عليه المستخدم. كما تضيف مربعات نص لرسالة الإعلام وعلامة اسم المستخدم التي يجب أن تتلقى الإشعار التالي:

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
    
        <TextBlock Grid.Row="0" Text="Notify Users" HorizontalAlignment="Center" FontSize="48"/>
    
        <StackPanel Grid.Row="1" VerticalAlignment="Center">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="0" Grid.ColumnSpan="3" Text="Username" FontSize="24" Margin="20,0,20,0"/>
                <TextBox Name="UsernameTextBox" Grid.Row="1" Grid.ColumnSpan="3" Margin="20,0,20,0"/>
                <TextBlock Grid.Row="2" Grid.ColumnSpan="3" Text="Password" FontSize="24" Margin="20,0,20,0" />
                <PasswordBox Name="PasswordTextBox" Grid.Row="3" Grid.ColumnSpan="3" Margin="20,0,20,0"/>
    
                <Button Grid.Row="4" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center"
                            Content="1. Login and register" Click="LoginAndRegisterClick" Margin="0,0,0,20"/>
    
                <ToggleButton Name="toggleWNS" Grid.Row="5" Grid.Column="0" HorizontalAlignment="Right" Content="WNS" IsChecked="True" />
                <ToggleButton Name="toggleFCM" Grid.Row="5" Grid.Column="1" HorizontalAlignment="Center" Content="FCM" />
                <ToggleButton Name="toggleAPNS" Grid.Row="5" Grid.Column="2" HorizontalAlignment="Left" Content="APNS" />
    
                <TextBlock Grid.Row="6" Grid.ColumnSpan="3" Text="Username Tag To Send To" FontSize="24" Margin="20,0,20,0"/>
                <TextBox Name="ToUserTagTextBox" Grid.Row="7" Grid.ColumnSpan="3" Margin="20,0,20,0" TextWrapping="Wrap" />
                <TextBlock Grid.Row="8" Grid.ColumnSpan="3" Text="Enter Notification Message" FontSize="24" Margin="20,0,20,0"/>
                <TextBox Name="NotificationMessageTextBox" Grid.Row="9" Grid.ColumnSpan="3" Margin="20,0,20,0" TextWrapping="Wrap" />
                <Button Grid.Row="10" Grid.ColumnSpan="3" HorizontalAlignment="Center" Content="2. Send push" Click="PushClick" Name="SendPushButton" />
            </Grid>
        </StackPanel>
    </Grid>
    
  9. في مستكشف الحلول، افتح الملف MainPage.xaml.cs للمشروعين (Windows 8.1)و(Windows Phone 8.1). إضافة العبارات التالية using في الجزء العلوي من كلا الملفين:

    using System.Net.Http;
    using Windows.Storage;
    using System.Net.Http.Headers;
    using Windows.Networking.PushNotifications;
    using Windows.UI.Popups;
    using System.Threading.Tasks;
    
  10. في MainPage.xaml.cs لمشروع WindowsApp، أضف العضو التالي إلى الفئة MainPage. التأكد من الاستبدال <Enter Your Backend Endpoint> بنقطة النهاية الخلفية الفعلية التي حُصل عليها مسبَقًا. على سبيل المثال، ⁧http://mybackend.azurewebsites.net⁩.

    private static string BACKEND_ENDPOINT = "<Enter Your Backend Endpoint>";
    
  11. إضافة التعليمة البرمجية أدناه إلى فئة MainPage في MainPage.xaml.cs للمشروعين (Windows 8.1) و(Windows Phone 8.1).

    الأسلوب PushClickهو معالج النقر لزر إرسال Send Push. وهو يستدعي الخلفية لدفع إشعار لجميع الأجهزة مع علامة اسم المستخدم الذي يطابق المعلمة to_tag. يتم إرسال رسالة الإعلام كمحتوى JSON في نص الطلب.

    الأسلوب LoginAndRegisterClickهو معالج النقر لزر إرسال Login and register. يخزن رمز المصادقة الأساسي (يمثل أي رمز مميز يستخدمه نظام المصادقة الخاص بك) في التخزين المحلي، ثم يستخدم RegisterClient للتسجيل للحصول على الإشعارات باستخدام الواجهة الخلفية.

    private async void PushClick(object sender, RoutedEventArgs e)
    {
        if (toggleWNS.IsChecked.Value)
        {
            await sendPush("wns", ToUserTagTextBox.Text, this.NotificationMessageTextBox.Text);
        }
        if (toggleFCM.IsChecked.Value)
        {
            await sendPush("fcm", ToUserTagTextBox.Text, this.NotificationMessageTextBox.Text);
        }
        if (toggleAPNS.IsChecked.Value)
        {
            await sendPush("apns", ToUserTagTextBox.Text, this.NotificationMessageTextBox.Text);
    
        }
    }
    
    private async Task sendPush(string pns, string userTag, string message)
    {
        var POST_URL = BACKEND_ENDPOINT + "/api/notifications?pns=" +
            pns + "&to_tag=" + userTag;
    
        using (var httpClient = new HttpClient())
        {
            var settings = ApplicationData.Current.LocalSettings.Values;
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", (string)settings["AuthenticationToken"]);
    
            try
            {
                await httpClient.PostAsync(POST_URL, new StringContent("\"" + message + "\"",
                    System.Text.Encoding.UTF8, "application/json"));
            }
            catch (Exception ex)
            {
                MessageDialog alert = new MessageDialog(ex.Message, "Failed to send " + pns + " message");
                alert.ShowAsync();
            }
        }
    }
    
    private async void LoginAndRegisterClick(object sender, RoutedEventArgs e)
    {
        SetAuthenticationTokenInLocalStorage();
    
        var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
    
        // The "username:<user name>" tag gets automatically added by the message handler in the backend.
        // The tag passed here can be whatever other tags you may want to use.
        try
        {
            // The device handle used is different depending on the device and PNS.
            // Windows devices use the channel uri as the PNS handle.
            await new RegisterClient(BACKEND_ENDPOINT).RegisterAsync(channel.Uri, new string[] { "myTag" });
    
            var dialog = new MessageDialog("Registered as: " + UsernameTextBox.Text);
            dialog.Commands.Add(new UICommand("OK"));
            await dialog.ShowAsync();
            SendPushButton.IsEnabled = true;
        }
        catch (Exception ex)
        {
            MessageDialog alert = new MessageDialog(ex.Message, "Failed to register with RegisterClient");
            alert.ShowAsync();
        }
    }
    
    private void SetAuthenticationTokenInLocalStorage()
    {
        string username = UsernameTextBox.Text;
        string password = PasswordTextBox.Password;
    
        var token = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(username + ":" + password));
        ApplicationData.Current.LocalSettings.Values["AuthenticationToken"] = token;
    }
    
  12. افتح App.xaml.cs وابحث عن استدعاء InitNotificationsAsync() في معالج الأحداث OnLaunched(). التعليق على الاستدعاء أو حذفه إلى InitNotificationsAsync(). يهيئ معالج الزر تسجيلات الإعلام:

    protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
        //InitNotificationsAsync();
    
  13. انقر بزر الماوس الأيمن فوق مشروع WindowsApp وانقر فوق Add، ثم انقر فوق Class. قم بتسمية الفئة RegisterClient.cs، ثم انقر فوق OK لإنشاء الفئة.

    هذه الفئة تلتف باستدعاءات REST المطلوبة للاتصال بخلفية التطبيق، من أجل التسجيل لدفع الإخطارات. كما أنه يخزن محليّاً registrationIds الم نشأة من مركز الإعلام كما هو مفصل في Registering from your app backend. فهي تستخدم رمز مصادقة مخزناً في التخزين المحلي عند نقر زر Login and register.

  14. أضف عبارات using التالية في الجزء العلوي من ملف RegisterClient.cs:

    using Windows.Storage;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using Newtonsoft.Json;
    using System.Threading.Tasks;
    using System.Linq;
    
  15. إضافة التعليمة البرمجية التالية داخل تعريف الفئة RegisterClient:

    private string POST_URL;
    
    private class DeviceRegistration
    {
        public string Platform { get; set; }
        public string Handle { get; set; }
        public string[] Tags { get; set; }
    }
    
    public RegisterClient(string backendEndpoint)
    {
        POST_URL = backendEndpoint + "/api/register";
    }
    
    public async Task RegisterAsync(string handle, IEnumerable<string> tags)
    {
        var regId = await RetrieveRegistrationIdOrRequestNewOneAsync();
    
        var deviceRegistration = new DeviceRegistration
        {
            Platform = "wns",
            Handle = handle,
            Tags = tags.ToArray<string>()
        };
    
        var statusCode = await UpdateRegistrationAsync(regId, deviceRegistration);
    
        if (statusCode == HttpStatusCode.Gone)
        {
            // regId is expired, deleting from local storage & recreating
            var settings = ApplicationData.Current.LocalSettings.Values;
            settings.Remove("__NHRegistrationId");
            regId = await RetrieveRegistrationIdOrRequestNewOneAsync();
            statusCode = await UpdateRegistrationAsync(regId, deviceRegistration);
        }
    
        if (statusCode != HttpStatusCode.Accepted && statusCode != HttpStatusCode.OK)
        {
            // log or throw
            throw new System.Net.WebException(statusCode.ToString());
        }
    }
    
    private async Task<HttpStatusCode> UpdateRegistrationAsync(string regId, DeviceRegistration deviceRegistration)
    {
        using (var httpClient = new HttpClient())
        {
            var settings = ApplicationData.Current.LocalSettings.Values;
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", (string) settings["AuthenticationToken"]);
    
            var putUri = POST_URL + "/" + regId;
    
            string json = JsonConvert.SerializeObject(deviceRegistration);
                            var response = await httpClient.PutAsync(putUri, new StringContent(json, Encoding.UTF8, "application/json"));
            return response.StatusCode;
        }
    }
    
    private async Task<string> RetrieveRegistrationIdOrRequestNewOneAsync()
    {
        var settings = ApplicationData.Current.LocalSettings.Values;
        if (!settings.ContainsKey("__NHRegistrationId"))
        {
            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", (string)settings["AuthenticationToken"]);
    
                var response = await httpClient.PostAsync(POST_URL, new StringContent(""));
                if (response.IsSuccessStatusCode)
                {
                    string regId = await response.Content.ReadAsStringAsync();
                    regId = regId.Substring(1, regId.Length - 2);
                    settings.Add("__NHRegistrationId", regId);
                }
                else
                {
                    throw new System.Net.WebException(response.StatusCode.ToString());
                }
            }
        }
        return (string)settings["__NHRegistrationId"];
    
    }
    
  16. احفظ جميع التغييرات التي قمت بإجرائها.

اختبار التطبيق

  1. تشغيل التطبيق على كل من Windows.

  2. أدخل UsernameوPassword كما هو موضح في الشاشة أدناه. يجب أن تختلف عن اسم المستخدم وكلمة المرور التي تدخلها على Windows Phone.

  3. انقر Log in and register ثم تحقق من مربع حوار يظهر أنك قمت بتسجيل الدخول. هذه التعلمية البرمجية تمكن زر ⁧⁩Send Push⁧⁩.

    لقطة شاشة لتطبيق مراكز الإعلام تظهر اسم المستخدم وكلمة المرور مدخلتين.

  4. في حقل Recipient Username Tag، أدخل اسم المستخدم المسجل. أدخل رسالة إعلام وانقر فوق Send Push.

  5. تتلقى الأجهزة التي تم تسجيلها مع علامة اسم المستخدم المطابقة رسالة الإعلام فقط.

    لقطة شاشة لتطبيق مراكز الإعلام تظهر الرسالة التي تم دفعها.

الخطوات التالية

في هذا البرنامج التعليمي، تعلمت كيفية دفع الإشعارات إلى مستخدمين محددين لديهم علامات مرتبطة بتسجيلاتهم. لمعرفة طريقة عرض الإعلامات إلى أجهزة Android معينة، الدخول إلى البرنامج التعليمي التالي: