بررسی یک حرکت ساده RealTime مبتنی بر SignalR و Blazor WASM

به نام خدا

اگر نوشته های قبلی بنده را دنبال کرده باشید، اینجانب به عنوان یک DOT NET Evangelist همواره در حال بازی کردن با ابداعات ماکروسافت هستم و چون چیز دیگری هم سرم نمی شود، کلن فقط ماکروسافت را قبول دارم و در مورد هر چیز دیگری صحبت کنید، فحش میدهم ( البته اگر غلط املایی هم بگیرید، باز هم فحش میدهم)، اما خدا وکیلی این SignalR یکی خیلی قوی است و دیگری هم اینکه کسی زیاد حواسش بهش نبوده و شاید کسی دقیق نشده ببیند چقدر میشود با این تکنولوژی کارها را ساده کرد و پول خوب ازش در آورد. حالا برای اینکه صحبت به درازا نکشد، شروع میکنیم.

مواد لازم :

- دانش دات نت کور

- دانش HTML به مقدار لازم

- نصب داشتن Visual Studio 2019 ( خانمهای خانه دار عزیز توجه کنند که بهتر است همیشه آخرین آپدیت را داشته باشند).

- حوصله خواندن چرندیات من به مقدار زیاد

هدف پروژه در پایان : داشتن یک API ساده که با Fire کردن آن توسط PostMan مثلن، یک پیام به کلاینتها ارسال و در Browser ما یک Application تولید شده توسط Blazor را باز کرده، پیام مشاهده و در کل پیام بدون رفرش یا دست زدن به صفحه در Web Application ما نمایش داده شده و مشخص شود که پیامی از سمت سرور آمده است. دقت کنید که کلاینت باید قبلن خودش را کانکت کرده باشد تا پیامها را دریافت کند.

اجازه بدهید خیلی کوتاه بررسی کنیم اصلن RealTime یعنی چی ؟.

مفهوم RealTime یعنی کل APP یا بخش لازمه آن در هنگام بروز یک Event آپدیت گردد. مثلن واتزآپ را تصور کنید، قرار نیست یک دکمه جایی باشد و شما مرتب کلیک کنید و آخرین پیامهای دریافت شده را داشته باشید. هر بار پیامی ارسال شود، به صورت خودبخود به Chat Application شما ارسال خواهد شد.

حال در چند خط ببینیم SignalR چیست ؟

سیگنال آر یک تکنولوژی ساخته شده توسط ماکروسافت برای Communicate بین سرور و کلاینت است .

سوال : آیا بدون سیگنال آر نمیشود کلاینت و سرور با همدیگر تماس داشته باشند و از تغییرات انجام شده آگاه شوند؟.

پاسخ مثبت است، ولی مثلن باید یک تایمر جایی داشته باشید و هر مثلن 5 ثانیه یکبار یک متد را صدا بزنید تا از آخرین تغییرات آگاه شوید. اما با استفاده از تکنولوژیهای RealTime دیگر نیازی نیست چنین کاری انجام شود و فقط در لحظاتی که تغییری رخ دهد شما دست به Update و ارسال Event خواهید زد.

اگر به مباحث تئوری بیشتری نیاز دارید، در کورسهای آموزشی فراوان پیدا میشود. به آنها مراجعه کنید چون اینجا دیگر پایان مباحث تئوری است. میرویم یک پروژه در VS.NET می سازیم و شروع میکنیم.

یک Solution جدید به نام Realtime2021 میسازیم.

به چه دلیل Solution ساختم ؟. چون 2 پروژه جدا درون آن نیاز دارم که در ادامه خواهیم ساخت.

اول یک پروژه Blazor WASM میسازم.

یک پروژه Blazor Wasm ساده به Solution من اضافه گردید.

حالا یک پروژه WebApi هم به این Solution اضافه خواهم کرد .

یعنی الان وضعیت ما این شکلی است

در ابتدا یک Controller ساده برای ارسال Post Request ایجاد میکنم.

چون باید بین سرور و کلاینت رابطه برقرار شود و این دو در 2 آدرس و پورت جدا اجرا خواهند شد، اجازه بدهید قبل از اینکه گرفتار بشویم یا فراموش کنیم، مشکل CORS را در سمت سرور حل کنیم. لطفن اگر اطلاع درستی از CORS ندارید، با مطالعه دقیق این مشکل را برطرف کنید چون در مبحث ما توضیح این مطلب جایی نخواهد داشت و ما فقط با یک پیاده سازی ساده جلو بروز آنرا خواهیم گرفت.

برای حل مشکل CORS ، باید به سراغ Startup.cs برویم و مانند شکل زیر عمل کنیم

پس از حل کردن مشکل CORS باید نیازمندیهای SignalR را در سمت سرور در پروژه ایجاد کنیم. پس Dependency ها را باید با استفاده از Nuget Package ها ایجاد کنیم.

در ابتدا در پروژه سرور این بسته را نصب کنید

Microsoft.AspNetCore.SignalR;

در SignalR با یک کانسپت اصلی به نام Hub سر و کار داریم. این Hub عملن درگاهی است که کلاینت و سرور از طریق آن با همدیگر صحبت میکنند. این دوست عزیز Hub را باید بسازیم و چیزی نیست که خود بخود موجود باشد یا بوجود بیاید، پس یک کلاس به پروژه سرور اضافه میکنم و مطابق تصویر زیر آنرا ایجاد میکنم.

اگر دقت کنید، من فقط یک فولدر ساختم و کلاس NotificationHub را درون آن ساختم و تمام. این کلاس از Base Class درون لایبرری سیگنال آر به نام Hub ارث بری کرده است. همین.

حالا باز باید تنظیماتی را برای فعال کردن و راه اندازی SignalR درون Startup.Cs داشته باشیم.

تصویر بالا نشان میدهد فقط 2 خط تغییرات داشتم و تمام.

برویم سراغ Controller و ببینم آنجا چه باید کرد .

به تصویر بالا از کنترلر من دقت کنید.

1- فرآیند ساده DI شدن Hub

2- یک Action Method ساده از نوع Post که سبب ارسال یک پیام به Hub خواهد شد

خووووب ، برویم یک سری به پروژه نوع کلاینت بزنیم و آنچه لازم است را در آن پیاده کنیم .

اول از همه این پکیچ را از طریق Nuget در پروژه کلاینت نصب کنید

Microsoft.AspNetCore.SignalR.Client

اگر با ساختار Blazor WASM آشنا باشید، میدانید در فولدر Pages چه خبر است. من وارد Index.razor خواهم شد و یکسری تغییرات در آن خواهم داشت.

تغییرات را به صورت تکه تکه درون این Razor فایل بررسی خواهیم کرد.

در بالای فایل همان خط اول که بحث Route مشخص شده که من نباید در این مقاله در موردش توضیحی بدهم و کامل مشخص است که پس از اجرا اگر آدرس کلی پروژه با فقط / خالی صدا زده شود، به این صفحه Redirect خواهیم شد.

وضعیت آن خطی که با Using شروع شده است هم که برای سی شارپ کارها مثل روز باید روشن باشد،پس دیگر توضیحی در موردش نخواهیم داشت

یک تگ H1 دارم که فقط یک خط نوشته است و اصلن زشته برای برنامه نویس جماعت در مورد این من توضیحی بدهم و بود و نبودش هم فرقی نمیکند.

خط بعدی یک دکمه است که یک متد سمت سرور را صدا میزند که آنرا بعدن خواهیم نوشت و سبب اتصال یا قطع اتصال ما به Hub خواهد شد.

پس از آن وضعیت متصل بودن یا نبودن را به ما نشان میدهد که فقط نمایش یک متغیر String است که از سمت سرور مقدار دهی میشود و در ادامه آنرا در تحرکات سمت سرور صفحه خواهید دید.

در بلاک بعدی کد مشاهده میکنید که در آیتمهای درون Hub توسط یک Foreach ساده میچرخیم و هرآنچه باشد را در یک H4 میگذاریم و نمایش میدهیم که با فلش نمایش داده ام.

هر صفحه در Blazor میتواند کد سمت سرور هم داشته باشد که در صفحه ما یک مقدار هم مفصل خواهد بود.

این را همه میدانیم که برای کد سمت سرور نویسی باید یک بلاک Code داشته باشیم که البته میشود آنرا به یک فایل جدا هم منتقل کنیم. من اول متغیرهای درون بلاک Code را تعریف و آن را برای شما بررسی خواهم کرد. به تصویر زیر دقت کنید.

متغیر url آدرس پورت پروژه Server است که باید از قسمت Debug بعد از Property گرفتن از پروژه سرور بردارید

خط شماره 2 تعریف خود Connection متعلق به Hub است که بعدن در متدها باز و بسته میکنیم و از آن استفاده میکنیم.

خط سوم یک متغیر است برای مشخص شدن اینکه کانکشن برقرار است یا نه.

خط 4 فقط یک String است تا پس از بررسی وضعیت تماس یک کلمه درون آن بریزیم و درون UI وسط HTML ها همانطور که مشاهده کردید نمایش بدهیم.

در خط شماره 5 هم یک List از آیتمها تعریف کردیم که بعدن پیامهای درون Hub را درون آن بریزیم و همانطور که مشاهده کردید یک Foreach در کدها داشتیم تا هر آنچه در این لیست بود را در UI نمایش دهیم.

و اما متدهای مورد نیاز برای برقراری تماس و دریافت اطلاعات درون Hub

یک دکمه داشتیم که به یک متد سمت سرور وصل است. خوب آیتم شماره 1 همان متد است. کانکشن تعریف شده را میسازد و بر اساس Url که آنرا قبلن ایجاد کرده ایم آماده اتصال خواهد و دریافت فرمان خواهد بود، ولی هنوز متصل نیستیم. پس از آنکه _connection.StartAsync(); صدا زده شد متصل خواهیم بود، برای همین است که متغیر Bool را به True و مقدار متغیر String را "Yoho , you are connected...." قرار داده ایم . چون الان به دلیل وصل بودن خیلی خوشحالیم و حتی از خوشحالی بال در آورده ایم.

در قسمتی که با شماره 2 مشخص شده اتفاقاتی که با بسته شدن کانکشن رخ خواهد داد مشخص شده که فکر نکنم سخت باشد و نیاز به توضیحی داشته باشد.

قسمت 3 هم که نشان میدهد که اگر پیامی وارد Hub شد آنرا دریافت و به لیست ما اضافه کند و سپس به Satechange به UI اعلام کند تا آنچه کاربر میبیند را تغییر دهد.

یک تغییر غیر ضروری هم در Hub میتوانم داشته باشم تا اگر لازم شد بتوانم Break Point داشته باشم.

من فقط متد را Override کردم تا بتوانم وضعیت کانکشن را در لحظه اتصال کنترل کنم.

حالا زحمت بکشید تنظیمات زیر را اعمال کنید تا هر دو پروژه همزمان اجرا شوند.

وضعیت ایده آل پش از اجرا میتواند این شکلی باشد

من هنوز چیزی از سرور به سمت کلاینت نفرستاده ام و ضمنن هنوز وضعیت اتصال را هم به Connected که با زدن دکمه اتصال باید شود تغییر نداده ام.

حالا با PostMan آن API که نوشتم را صدا میزنم و یک پیام برای کلاینت میفرستم. دقت کنید قبل از آن دکمه کانکت را زده باشید و به درستی متصل باشید.

حالا اگر 50 تا کلاینت هم باز کنید و متصل شوید و پیامی از سرور ارسال کنید، خواهید دید که پیام برای همه ارسال و UI تغییر را نمایش خواهد داد.

این هم از یک ترکیب ساده SignalRو Blazor WASM

دیگر از این راحت تر برنامه نوشتم فکر نکنم شدنی باشد. بروید حالش را ببرید. سورسش را هم در کانال میگذارم، بروید حالش را ببرید.

نظر هیچ کدام از خوانندگان عزیز و گرامی برایم مهم نیست و اگر ایده های بیشتری دارید، خودتان بنویسید و آپلود کنید من هم استفاده میکنم. غلط املایی هم بگیرید فحش میدهم.

موفق و پیروز باشید

علی کلاهدوزان، 17 جنوری2021 ، مصادف با نمی دانم چندم دی ماه 1399