التشغيل السريع: إنشاء تطبيق يعرض عدد نجوم GitHub باستخدام Azure Functions وخدمة SignalR عبر C#‎

في هذه المقالة، ستتعلم كيفية استخدام SignalR Service وAzure Functions لإنشاء تطبيق بلا خادم باستخدام C# لبث الرسائل إلى العملاء.

إشعار

يمكنك الحصول على التعليمات البرمجية المذكورة في هذه المقالة من GitHub.

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

المتطلبات الأساسية التالية مطلوبة لهذا التشغيل السريع:

قم بإنشاء مثيل Azure SignalR Service

في هذا القسم، يمكنك إنشاء مثيل Azure SignalR أساسي لاستخدامه لتطبيقك. تستخدم الخطوات التالية مدخل Microsoft Azure لإنشاء مثيل جديد، ولكن يمكنك أيضا استخدام Azure CLI. لمزيد من المعلومات، راجع الأمر az signalr create في مرجع Azure SignalR Service CLI.

  1. سجل الدخول إلى مدخل Azure.
  2. في الجانب العلوي الأيسر من الصفحة، اختر+ إنشاء مورد.
  3. في صفحة إنشاء مورد، في مربع النص خدمة البحث والسوق، أدخل signalr ثم حدد SignalR Service من القائمة.
  4. في صفحة SignalR Service ، حدد Create.
  5. في علامة التبويب Basics ، يمكنك إدخال المعلومات الأساسية لمثيل SignalR Service الجديد. أدخل القيم التالية:
الحقل القيم المقترحة ‏‏الوصف
الاشتراك اختر اشتراكك حدد الاشتراك الذي تريد استخدامه لإنشاء مثيل خدمة SignalR جديد.
مجموعة الموارد إنشاء مجموعة موارد باسم SignalRTestResources يوصى باختيار أو إنشاء مجموعة موارد لموردك SignalR. من المفيد إنشاء مجموعة موارد جديدة لهذا البرنامج التعليمي بدلا من استخدام مجموعة موارد موجودة. لتحرير الموارد بعد إكمال البرنامج التعليمي، احذف مجموعة الموارد.

يؤدي حذف مجموعة موارد أيضا إلى حذف كافة الموارد التي تنتمي إلى المجموعة. لا يمكن التراجع عن هذا الإجراء. قبل حذف مجموعة موارد، تأكد من أنها لا تحتوي على موارد تريد الاحتفاظ بها.

للمزيد من المعلومات، يُرجى الرجوع إلى استخدام مجموعات الموارد لإدارة موارد Azure.
اسم المورد testsignalr أدخل اسم مورد مميزًا لاستخدامه في مورد SignalR. إذا تم أخذ testignalr بالفعل في منطقتك، أضف رقما أو حرفا حتى يكون الاسم فريدا.

يجب أن يكون الاسم سلسلة مكونة من 1 إلى 63 حرفًا وتتضمن الأرقام والحروف ورمز الواصلة فقط -. لا يمكن أن يبدأ الاسم أو ينتهي بحرف الواصلة، وأحرف الواصلة المتتالية غير صالحة.
المنطقة اختيار منطقتك حدد المنطقة المناسبة لمثيل SignalR Service الجديد.

خدمة Azure SignalR غير متوفرة حاليا في جميع المناطق. لمزيد من المعلومات، راجع توفر منطقة خدمة Azure SignalR
مستوى الأسعار حدد تغيير ثم اختر مجاني (التطوير/الاختبار فقط). اختر تحديد لتأكيد اختيارك لمستوى التسعير. تحتوي خدمة Azure SignalR على ثلاثة مستويات تسعير: Free وStandard وPremium. تستخدم البرامج التعليمية المستوى المجاني ، ما لم يتم ملاحظة خلاف ذلك في المتطلبات الأساسية.

لمزيد من المعلومات حول اختلافات الوظائف بين المستويات والتسعير، راجع تسعير خدمة Azure SignalR
وضع الخدمة اختر وضع الخدمة المناسب استخدم الافتراضي عند استضافة منطق مركز SignalR في تطبيقات الويب واستخدام خدمة SignalR كوكيل. استخدم Serverless عند استخدام تقنيات بلا خادم مثل Azure Functions لاستضافة منطق مركز SignalR.

الوضع الكلاسيكي هو فقط للتوافق مع الإصدارات السابقة ولا يوصى باستخدامه.

لمزيد من المعلومات، راجع وضع الخدمة في خدمة Azure SignalR.

لا تحتاج إلى تغيير الإعدادات في علامات التبويب الشبكات والعلامات لبرامج SignalR التعليمية.

  1. حدد الزر Review + create أسفل علامة التبويب Basics .
  2. في علامة التبويب Review + create ، راجع القيم ثم حدد Create. يستغرق الأمر بضع لحظات حتى يكتمل النشر.
  3. عند اكتمال النشر، حدد الزر Go to resource .
  4. في صفحة مورد SignalR، حدد Keys من القائمة على اليسار، ضمن الإعدادات.
  5. انسخ سلسلة الاتصال ion للمفتاح الأساسي. تحتاج إلى هذا سلسلة الاتصال لتكوين تطبيقك لاحقا في هذا البرنامج التعليمي.

إعداد وتشغيل Azure Function محلياً

ستحتاج إلى Azure Functions Core Tools لهذه الخطوة.

  1. إنشاء دليل فارغ وتغيير إلى الدليل باستخدام سطر الأوامر.

  2. تهيئة مشروع جديد.

    # Initialize a function project
    func init --worker-runtime dotnet
    
    # Add SignalR Service package reference to the project
    dotnet add package Microsoft.Azure.WebJobs.Extensions.SignalRService
    
  3. باستخدام محرر التعليمات البرمجية، قم بإنشاء ملف جديد باسم Function.cs. أضف التعليمات البرمجية التالية إلى Function.cs:

    using System;
    using System.IO;
    using System.Linq;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.Azure.WebJobs.Extensions.SignalRService;
    using Newtonsoft.Json;
    
    namespace CSharp
    {
        public static class Function
        {
            private static HttpClient httpClient = new HttpClient();
            private static string Etag = string.Empty;
            private static string StarCount = "0";
    
            [FunctionName("index")]
            public static IActionResult GetHomePage([HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req, ExecutionContext context)
            {
                var path = Path.Combine(context.FunctionAppDirectory, "content", "index.html");
                return new ContentResult
                {
                    Content = File.ReadAllText(path),
                    ContentType = "text/html",
                };
            }
    
            [FunctionName("negotiate")]
            public static SignalRConnectionInfo Negotiate(
                [HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req,
                [SignalRConnectionInfo(HubName = "serverless")] SignalRConnectionInfo connectionInfo)
            {
                return connectionInfo;
            }
    
            [FunctionName("broadcast")]
            public static async Task Broadcast([TimerTrigger("*/5 * * * * *")] TimerInfo myTimer,
            [SignalR(HubName = "serverless")] IAsyncCollector<SignalRMessage> signalRMessages)
            {
                var request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/azure/azure-signalr");
                request.Headers.UserAgent.ParseAdd("Serverless");
                request.Headers.Add("If-None-Match", Etag);
                var response = await httpClient.SendAsync(request);
                if (response.Headers.Contains("Etag"))
                {
                    Etag = response.Headers.GetValues("Etag").First();
                }
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    var result = JsonConvert.DeserializeObject<GitResult>(await response.Content.ReadAsStringAsync());
                    StarCount = result.StarCount;
                }
    
                await signalRMessages.AddAsync(
                    new SignalRMessage
                    {
                        Target = "newMessage",
                        Arguments = new[] { $"Current star count of https://github.com/Azure/azure-signalr is: {StarCount}" }
                    });
            }
    
            private class GitResult
            {
                [JsonRequired]
                [JsonProperty("stargazers_count")]
                public string StarCount { get; set; }
            }
        }
    }
    

    التعليمات البرمجية في Function.cs لها ثلاث دالات:

    • GetHomePage يستخدم للحصول على موقع ويب كعملاء.
    • Negotiate يستخدمه العميل للحصول على رمز مميز للوصول.
    • Broadcast يتم استدعاء دوريا للحصول على عدد النجوم من GitHub ثم بث الرسائل إلى جميع العملاء.
  4. واجهة العميل لهذا النموذج هي صفحة ويب. نقوم بعرض صفحة الويب باستخدام الدالة GetHomePage عن طريق قراءة محتوى HTML من content/index.html الملف. الآن دعونا ننشئ هذا الفهرس.html ضمن content الدليل الفرعي بالمحتوى التالي:

    <html>
    
    <body>
      <h1>Azure SignalR Serverless Sample</h1>
      <div id="messages"></div>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.min.js"></script>
      <script>
        let messages = document.querySelector('#messages');
        const apiBaseUrl = window.location.origin;
        const connection = new signalR.HubConnectionBuilder()
            .withUrl(apiBaseUrl + '/api')
            .configureLogging(signalR.LogLevel.Information)
            .build();
          connection.on('newMessage', (message) => {
            document.getElementById("messages").innerHTML = message;
          });
    
          connection.start()
            .catch(console.error);
      </script>
    </body>
    
    </html>
    
  5. تحديث لجعل *.csproj صفحة المحتوى في مجلد إخراج البنية.

    <ItemGroup>
      <None Update="content/index.html">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </None>
    </ItemGroup>
    
  6. تتطلب Azure Functions حساب تخزين للعمل. يمكنك تثبيت وتشغيل Azure Storage Emulator. أو يمكنك تحديث الإعداد لاستخدام حساب التخزين الحقيقي الخاص بك باستخدام الأمر التالي:

    func settings add AzureWebJobsStorage "<storage-connection-string>"
    
  7. لقد أوشكت على الانتهاء الآن. الخطوة الأخيرة هي تعيين سلسلة اتصال من SignalR Service إلى إعدادات Azure Function.

    1. تأكد من إنشاء مثيل SignalR Service بنجاح عن طريق البحث عن اسمه في مربع البحث في أعلى المدخل. حدد المثيل لفتحه.

      Search for the SignalR Service instance

    2. حدد "Keys" لعرض سلاسل الاتصال لمثيل SignalR Service.

      Screenshot that highlights the primary connection string.

    3. انسخ سلسلة الاتصال الأساسي، ثم قم بتشغيل الأمر التالي:

      func settings add AzureSignalRConnectionString "<signalr-connection-string>"
      
  8. تشغيل دالة Azure محليا:

    func start
    

    بعد تشغيل دالة Azure محليا، افتح http://localhost:7071/api/index، ويمكنك مشاهدة عدد النجوم الحالي. إذا كنت نجمة أو إلغاء نجمة في GitHub، فستحصل على عدد نجوم يتم تحديثه كل بضع ثوان.

تنظيف الموارد

إذا لم تكن تنوي متابعة استخدام هذا التطبيق، فاحذف كافة الموارد التي تم إنشاؤها بواسطة هذا التشغيل السريع باستخدام الخطوات التالية حتى لا تتحمل أي رسوم:

  1. من القائمة اليسرى في مدخل Azure، حدد مجموعات الموارد ثم حدد مجموعة الموارد التي أنشأتها. بدلاً من ذلك، يمكنك استخدام مربع البحث للبحث عن مجموعة الموارد باسمها.

  2. في النافذة التي ستفتح، حدد مجموعة الموارد، ثم انقر فوق حذف مجموعة الموارد.

  3. في النافذة الجديد، اكتب اسم مجموعة الموارد المراد حذفها، ثم انقر فوق حذف.

هل تواجه مشكلات؟ جرب دليل استكشاف الأخطاء وإصلاحها أو أخبرنا.

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

في هذا التشغيل السريع، قمت ببناء وتشغيل تطبيق بلا خادم في الوقت الحقيقي محليا. بعد ذلك، تعرف على المزيد حول الاتصال ثنائي الاتجاه بين العملاء وAzure Functions باستخدام Azure SignalR Service.