کتاب Razor Components Succinctly
OVERVIEW
Razor components are specific building blocks within the Blazor framework. They can perform many roles: representing a specific piece of the user interface, a view component, or a tag helper; or representing a layout or an entire page. In Razor Components Succinctly, you will explore how to create and work with both simple and advanced Razor components. Longtime Succinctly author Ed Freitas will show you how to write a basic component using one-way data binding and events, and then two-way data binding, event callbacks, life cycle methods, and component references. Finally, you'll see how to enable component reuse by creating a component template.
TABLE OF CONTENTS
Razor Components
Setup and Fundamentals
Component Fundamentals
Component Features
Using Components
Templating
Author
Ed Freitas
ISBN
978-1-64200-211-9
Published on
April 16, 2021
Pages
102
In this video we perform a full step by step build of a .NET MAUI App that we test on both Windows and Android. The app interacts with a separate .NET 6 API that we also build step by step.
Level: Beginner
⏲️ Time Codes ⏲️
Theory
- 0:48 Welcome
- 03:13 App demo
- 06:07 Course overview
- 09:14 Ingedients
- 10:10 What is .NET MAUI?
- 12:48 How MAUI works
- 15:14 MAUI project anatomy
- 19:47 MAUI App start up sequence
- 22:29 UI Conepts
- 28:21 XAML vs C#
- 30:29 Solution Architecture
- 31:41 Application Architecture
API Build
- 35:31 API Project Set up
- 42:41 API Model definition
- 44:47 API Db Context
- 47:13 Connection String
- 52:19 Migrations
- 56:31 API Read Endpoint
- 1:01:58 API Create Endpoint
- 1:08:15 API Update Endpoint
- 1:12:57 API Delete Endpoint
MAUI App Build
- 1:17:21 MAUI App Project Set up
- 1:21:00 Android Device Manager
- 1:25:08 MAUI Model definition
- 1:31:16 Data Service Interface
- 1:35:40 Data Service Implementation
- 1:47:27 Data Service Read Method
- 1:53:34 Data Service Create Method
- 1:58:48 Data Service Delete Method
- 2:01:53 Data Service Update Method
- 2:05:41 Android environment config
- 2:11:00 Architecture check point
- 2:11:54 Register MainPage for DI
- 2:14:13 MainPage code-behind
- 2:21:03 MainPage XAML Layout
- 2:30:19 Re-work MainPage layout
- 2:35:12 Add another page (ManagePage)
- 2:38:01 Adding a Route
- 2:30:01 Regiter ManagePage for DI
- 2:40:29 Complete MainPage code-behind
- 2:45:12 ManagePage code-behind
- 2:51:16 QueryProperty
- 2:57:34 ManagePage XMAL
- 3:07:56 Run on Windows
- 3:09:30 Re-work ManagePage layout
- 3:16:26 Using HttpClientFactory
Outro
- 3:21:02 Wrap up and thanks
- 3:21:31 Supporter Credits
بنده سرور مجازی 2008 رو مورد آزمایش قرار دادم :
با خطای 502.5 مواجه شدم
که طبق نکاتی که در لینک پایین تصویر وجود داشت :
Hosting bundle not installed or server not restarted
- Browser: 502.3 Bad Gateway: There was a connection error while trying to route the request.
- Application Log: Process ‘0’ failed to start. Port = PORT, Error Code = ‘-2147024894’.
- ASP.NET Core Module Log: Log file created but empty
و تغییری که در فایل webconfig جهت log کردن انجام دادم مورد زیر از توضیحات بالا مشاهده شد :
ASP.NET Core Module Log: Log file created but empty
که پس از Restart ویندوز سرور - مشکل خالی بودن فایلهای لاگ برطرف شد و اینبار در فایلهای لاگ با متن خطای زیر مواجه شدم:
Failed to load the dll from [C:\Program Files\dotnet\host\fxr\1.0.1\hostfxr.dll], HRESULT: 0x80070057
در حال حاضر در صدد رفع این مشکل هستم.
شاید شما هم مطلع شده باشید که npm کتاب خانه @aspnet/signalr-client را منسوخ شده اعلام کرد. از این پس شما برای سوکت زدن بین .net و انگولار میتوانید از کتابخانه @aspnet/signalr استفاده کنید. برای اطلاعات بیشتر به سایت npm مراجعه نمائید. همچنین میتوانید در مقاله معرفی شده آموزش کار با کتابخانه جدید و همچنین ساخت یک پروژه ارسال پیام را بیاموزید.
Docker for Windows چگونه از هر دوی کانتینرهای ویندوزی و لینوکسی پشتیبانی میکند؟
زمانیکه docker for windows را اجرا میکنیم، سرویسی را ایجاد میکند که سبب اجرای پروسهی ویژهای به نام com.docker.proxy.exe میشود:
هنگامیکه برای مثال فرمان docker run nginx را توسط Docker CLI اجرا میکنیم، Docker CLI از طریق واسط یاد شده، دستورات را به MobyLinuxVM منتقل میکند. به این صورت است که امکان اجرای Linux Containers، بر روی ویندوز میسر میشوند:
اکنون اگر به Windows Containers سوئیچ کنیم (از طریق کلیک راست بر روی آیکن Docker در قسمت Tray Icons ویندوز)، پروسهی dockerd.exe یا docker daemon شروع به کار خواهد کرد:
اینبار اگر مجددا از Docker CLI برای اجرای مثلا IIS Container استفاده کنیم، دستور ما از طریق واسطهای com.docker.proxy و dockerd، به کانتینر ویندوزی منتقل و اجرا میشود:
نگاهی به معماری Docker بر روی ویندوز سرور
داکر بر روی ویندوز سرور، تنها به همراه موتور مدیریت کنندهی Windows Containers است:
در اینجا با صدور فرمانهای Docker CLI، پیامها مستقیما به dockerd یا موتور داکر بر روی ویندوز سرور ارسال شده و سپس کار اجرا و مدیریت یک Windows Container انجام میشود.
نصب Docker بر روی ویندوز سرور
جزئیات مفصل و به روز Windows Containers را همواره میتوانید در این آدرس در سایت مستندات مجازی سازی مایکروسافت مطالعه کنید (قسمت Container Host Deployment - Windows Server آن). پیشنیاز کار با آن نیز نصب حداقل ویندوز سرور 2016 میباشد و بهتر است تمام به روز رسانیهای آنرا نیز نصب کرده باشید؛ چون تعدادی از بهبودهای کار با کانتینرهای آن، به همراه به روز رسانیها آن ارائه شدهاند.
برای شروع به نصب، نیاز است کنسول PowerShell ویندوز را با دسترسی Admin اجرا کنید.
سپس اولین دستوراتی را که نیاز است اجرا کنید، کار نصب موتور Docker و CLI آنرا به صورت خودکار بر روی ویندوز سرور انجام میدهند:
Install-Module -Name DockerMsftProvider -Repository PSGallery -Force Install-Package -Name docker -ProviderName DockerMsftProvider Restart-Computer -Force
- به علاوه اگر دستور *get-service *docker را در کنسول PowerShell صادر کنید، مشاهده خواهید کرد که سرویس جدیدی را به نام Docker نیز نصب و راه اندازی کردهاست که به dockerd.exe اشاره میکند.
- و یا اگر در کنسول PowerShell دستور docker را صادر کنید، ملاحظه خواهید کرد که CLI آن، فعال و قابل استفادهاست. برای مثال، دستور docker version را صادر کنید تا بتوانید نگارش docker نصب شده را ملاحظه نمائید.
اجرای Image مخصوص NET Core. بر روی ویندوز سرور
تگهای مختلف Image مخصوص NET Core. را در اینجا ملاحظه میکنید. در ادامه قصد داریم tag مرتبط با nanoserver آنرا نصب کنیم (با حجم 802MB):
docker run microsoft/dotnet:nanoserver
docker run -it microsoft/dotnet:nanoserver
چرا حجم Image مخصوص NET Core. نگارش nanoserver آن حدود 800 مگابایت است؟
در مثال قبلی، دسترسی به command prompt مجزایی نسبت به command prompt اصلی سیستم، در داخل یک container، شاید اندکی غیر منتظره بود و اکنون این سؤال مطرح میشود که یک image، شامل چه چیزهایی است؟
یک image شاید در ابتدای کار صرفا شامل فایلهای اجرایی یک برنامهی خاص به نظر برسد؛ اما زمانیکه قرار است تبدیل به یک container قابل اجرا شود، شامل بسیاری از فایلهای دیگر نیز خواهد شد. برای درک این موضوع نیاز است لایههای نرم افزاری که یک سیستم را تشکیل میدهند، بررسی کنیم:
در این تصویر از پایینترین لایهای را که با سخت افزار ارتباط برقرار میکند تا بالاترین لایهی موجود نرم افزاری را مشاهده میکنید. دراینجا هر چیزی را که در ناحیهی کرنل قرار نمیگیرد، User Space مینامند. برنامههای قرار گرفتهی در User Space برای کار با سخت افزار نیاز است با کرنل ارتباط برقرار کنند و برای این منظور از System Calls استفاده میکنند که عموما کتابخانههایی هستند که جزئی از سیستم عامل میباشند؛ مانند API ویندوز. برای مثال MongoDB توسط Win32 API و System Calls، فرامینی را به کرنل منتقل میکند.
در روش متداول توزیع و نصب نرم افزار، ما عموما همان بالاترین سطح را توزیع و نصب میکنیم؛ برای مثال خود MongoDB را. در اینجا نصاب MongoDB فرض میکند که در سیستم جاری، تمام لایههای دیگر، موجود و آمادهی استفاده هستند و اگر اینگونه نباشد، به مشکل برخواهد خورد و اجرا نمیشود. برای اجتناب از یک چنین مشکلاتی مانند عدم حضور وابستگیهایی که یک برنامه برای اجرا نیاز دارد، imageهای docker، نحوهی توزیع نرم افزارها را تغییر دادهاند. اینبار یک image بجای توزیع فقط MongoDB، شامل تمام قسمتهای مورد نیاز User Space نیز هست:
به این ترتیب دیگر مشکلاتی مانند عدم وجود یک وابستگی یا حتی وجود یک وابستگی غیرسازگار با نرم افزار مدنظر، وجود نخواهند داشت. حتی میتوان تصویر فوق را به صورت زیر نیز خلاصه کرد:
به همین جهت بود که برای مثال در قسمت قبل موفق شدیم IIS مخصوص ویندوز سرور با تگ nanoserver را بر روی ویندوز 10 که بسیاری از وابستگیهای مرتبط را به همراه ندارد، با موفقیت اجرا کنیم.
به علاوه چون یک container صرفا به معنای یک running process از یک image است، هر فایل اجرایی داخل آن image را نیز میتوان به صورت یک container اجرا کرد؛ مانند cmd.exe داخل image مرتبط با NET Core. که آنرا بررسی کردیم.
کارآیی Docker Containers نسبت به ماشینهای مجازی بسیار بیشتر است
مزیت دیگر یک چنین توزیعی این است که اگر چندین container در حال اجرا را داشته باشیم:
در نهایت تمام آنها فقط با یک لایهی کرنل کار میکنند و آن هم کرنل اصلی سیستم جاری است. به همین جهت کارآیی docker containers نسبت به ماشینهای مجازی بیشتر است؛ چون هر ماشین مجازی، کرنل مجازی خاص خودش را نسبت به یک ماشین مجازی در حال اجرای دیگر دارد. در اینجا برای ایجاد یک لایه ایزولهی اجرای برنامهها، تنها کافی است یک container جدید را اجرا کنیم و در این حالت وارد فاز بوت شدن یک سیستم عامل کامل، مانند ماشینهای مجازی نمیشویم.
شاید مطابق تصویر فوق اینطور به نظر برسد که هرچند تمام این containers از یک کرنل استفاده میکنند، اما اگر قرار باشد هر کدام OS Apps & Libs خاص خودشان را در حافظه بارگذاری کنند، با کمبود شدید منابع روبرو شویم. دقیقا مانند حالتیکه چند ماشین مجازی را اجرا کردهایم و دیگر سیستم اصلی قادر به پاسخگویی به درخواستهای رسیده به علت کمبود منابع نیست. اما در واقعیت، یک image داکر، از لایههای مختلفی تشکیل میشود که فقط خواندنی هستند و غیرقابل تغییر و زمانیکه docker یک لایهی فقط خواندنی را در حافظه بارگذاری کرد، اگر container دیگری، از همان لایهی تعریف شده، در image خود نیز استفاده میکند، لایهی بارگذاری شدهی فقط خواندنی در حال اجرای موجود را با آن به اشتراک میگذارد (مانند تصویر زیر). به این ترتیب میزان مصرف منابع docker containers نسبت به ماشینهای مجازی بسیار کمتر است:
روش کنترل پروسهای که درون یک کانتینر اجرا میشود
با اجرای دستور docker run -it microsoft/dotnet:nanoserver ابتدا به command prompt داخلی و مخصوص این container منتقل میشویم و سپس میتوان برای مثال با NET Core CLI. کار کرد. اما امکان اجرای این CLI به صورت زیر نیز وجود دارد:
docker run -it microsoft/dotnet:nanoserver dotnet --info
بدیهی است در این حالت تمام فایلهای اجرایی داخل این container را نیز میتوان اجرا کرد. برای مثال میتوان کنسول پاورشل داخل این container را اجرا کرد:
docker run -it microsoft/dotnet:nanoserver powershell
هر کانتینر دارای یک File System ایزولهی خاص خود است
تا اینجا دریافتیم که هر image، به همراه فایلهای user space مورد نیاز خود نیز میباشد. به عبارتی هر image یک file system را نیز ارائه میدهد که تنها درون همان container قابل دسترسی میباشد و از مابقی سیستم جاری ایزوله شدهاست.
برای آزمایش آن، کنسول پاورشل را در سیستم میزبان (سیستم عامل اصلی که docker را اجرا میکند)، باز کرده و دستور \:ls c را صادر کنید. به این ترتیب میتوانید لیست پوشهها و فایلهای موجود در درایو C میزبان را مشاهده نمائید. سپس دستور docker run -it microsoft/dotnet:nanoserver powershell را اجرا کنید تا به powershell داخل کانتینر NET Core. دسترسی پیدا کنیم. اکنون دستور \:ls c را مجددا اجرا کنید. خروجی آن کاملا متفاوت است نسبت به گزارشی که پیشتر بر روی سیستم میزبان تهیه کردیم؛ دقیقا مانند اینکه هارد درایو یک container متفاوت است با هارد درایو سیستم میزبان.
این تصویر زمانی تهیه شدهاست که دستور docker run یاد شده را صادر کردهایم و درون powershell آن قرار داریم. همانطور که مشاهده میکنید یک Disk جدید، به ازای این Container در حال اجرا، به سیستم میزبان اضافه شدهاست. این Disk زمانیکه در powershell داخل container، دستور exit را صادر کنیم، بلافاصله محو میشود. چون پروسهی container، به این ترتیب خاتمه یافتهاست.
اگر دستور docker run یاد شده را دو بار اجرا کنیم، دو Disk جدید ظاهر خواهند شد:
یک نکته: اگر بر روی این درایوهای مجازی کلیک راست کرده، گزینهی change drive letter or path را انتخاب نموده و یک drive letter را به آنها نسبت دهید، میتوانید محتویات داخل آنها را توسط Windows Explorer ویندوز میزبان نیز به صورت یک درایو جدید، مشاهده کنید.
خلاصهای از ایزوله سازیهای کانتینرها تا به اینجا
تا اینجا یک چنین ایزوله سازیهایی را بررسی کردیم:
- ایزوله سازی File System و وجود یک disk مجازی مجزا به ازای هر کانتینر در حال اجرا.
- پروسههای کانتینرها از پروسههای میزبان ایزوله هستند. برای مثال اگر دستور get-process را داخل یک container اجرا کنید، خروجی آن با خروجی اجرای این دستور بر روی سیستم میزبان یکی نیست. یعنی نمیتوان از داخل کانتینرها، به پروسههای میزبان دسترسی داشت و دخل و تصرفی را در آنها انجام داد که از لحاظ امنیتی بسیار مفید است. هر چند اگر به task manager ویندوز میزبان مراجعه کنید، میتوان پروسههای داخل یک container را توسط Job Object ID یکسان آنها تشخیص دهید (مثال آخر قسمت قبل)، اما یک container، قابلیت شمارش پروسههای خارج از مرز خود را ندارد.
- ایزوله سازی شبکه مانند کارت شبکهی مجازی کانتینر IIS که در قسمت قبل بررسی کردیم. برای آزمایش آن دستور ipconfig را در داخل container و سپس در سیستم میزبان اجرا کنید. نتیجهای را که مشاهده خواهید کرد، کاملا متفاوت است. یعنی network stack این دو کاملا از هم مجزا است. شبیه به اینکه به یک سیستم، چندین کارت شبکه را متصل کرده باشید. اینکار در اینجا با تعریف virtual network adaptors انجام میشود و لیست آنها را در قسمت «All Control Panel Items\Network Connections» سیستم میزبان میتوانید مشاهده کنید. یکی از مهمترین مزایای آن این است که اگر در یک container، وب سروری را بر روی پورت 80 آن اجرا کنید، مهم نیست که در سیستم میزبان، یک IIS در حال سرویس دهی بر روی پورت 80 هم اکنون موجود است. این دو پورت با هم تداخل نمیکنند.
- در حالت کار با Windows Containers، رجیستری کانتینر نیز از میزبان آن مجزا است و یا متغیرهای محیطی اینها یکی نیست. برای مثال دستور \:ls env را در کانتینر و سیستم میزبان اجرا کنید تا environment variables را گزارش گیری کنید. خروجی این دو کاملا متفاوت است. برای مثال حداقل computer name، user nameهای قابل مشاهدهی در این گزارشها، متفاوت است و یا دستور \:ls hkcu را در هر دو اجرا کنید تا خروجی رجیستری متعلق به کاربر جاری هر کدام را مشاهده کنید که در هر دو متفاوت است.
- در حالت کار با Linux Containers هر چیزی که ذیل عنوان namespace مطرح میشود مانند شبکه، PID، User، UTS، Mount و غیره شامل ایزوله سازی میشوند.
دو نوع Windows Containers وجود دارند
در ویندوز، Windows Server Containers و Hyper-V Containers وجود دارند. در این قسمت تمام کارهایی را که بر روی ویندوز سرور انجام دادیم، در حقیقت بر روی Windows Server Containers انجام شدند و تمام Containerهای ویندوزی را که در قسمت قبل بر روی ویندوز 10 ایجاد کردیم، از نوع Hyper-V Containers بودند.
تفاوت مهم اینها در مورد نحوهی پیاده سازی ایزوله سازی آنها است. در حالت Windows Server Containers، کار ایزوله سازی پروسهها توسط کرنل اشتراکی بین کانتینرها صورت میگیرد اما در Hyper-V Containers، این ایزوله سازی توسط hypervisor آن انجام میشود؛ هرچند نسبت به ماشینهای مجازی متداول بسیار سریعتر است، اما بحث به اشتراک گذاری کرنل هاست را که پیشتر در این قسمت بررسی کردیم، در این حالت شاهد نخواهیم بود. ویندوز سرور 2016 میتواند هر دوی این ایزوله سازیها را پشتیبانی کند، اما ویندوز 10، فقط نوع Hyper-V را پشتیبانی میکند.
روش اجرای Hyper-V Containers بر روی ویندوز سرور
در صورت نیاز برای کار با Hyper-V Containers، نیاز است مانند قسمت قبل، ابتدا Hyper-V را بر روی ویندوز سرور، فعالسازی کرد:
Install-WindowsFeature hyper-v Restart-Computer -Force
docker run -it --isolation=hyperv microsoft/dotnet:nanoserver powershell
dotnet new -i FeatherHttp.Templates::0.1.67-alpha.g69b43bed72 --nuget-source https://f.feedz.io/featherhttp/framework/nuget/index.json
Templates Short Name Language Tags ---------------------------------------------------------------------------------------------------------------------------------- FeatherHttp feather [C#] Web/ASP.NET/FeatherHttp
dotnet new feather --name todoAPI
همانطور که مشاهده میکنید پروژهی فوق تنها شامل دو فایل .csproj و Program.cs است. درون Program.cs و متد Main کار initialize کردن سرور HTTP صورت گرفته است. WebApplication.Create دقیقا همانند Host.CreateDefaultBuilder پروژههای ASP.NET Core عمل میکند؛ یعنی پیکربندی pipeline از قبیل اضافه کردن متغیرهای محیطی، خواندن از فایل JSON و ... را انجام میدهد اما با کد boilerplate کمتر. بنابراین خروجی WebApplication.Create یک ASP.NET Core Pipeline با قابلیت اضافه کردن تنظیمات دلخواه است. در ادامه جهت بررسی بیشتر Feather HTTP، یک مدل را به همراه یک سری دیتای In-memory به پروژه اضافه خواهیم کرد:
using System.Collections.Generic; using System.Text.Json.Serialization; using System.Linq; namespace todoAPI.Models { public class Todo { [JsonPropertyName("id")] public int Id { get; set; } [JsonPropertyName("title")] public string Title { get; set; } [JsonPropertyName("completed")] public bool Completed { get; set; } } public class TodoData { private readonly IList<Todo> _db = new List<Todo> { new Todo { Id = 1, Title = "Read book" }, new Todo { Id = 2, Title = "Watch an episode of Dark" }, new Todo { Id = 3, Title = "Publish a post on dotnettips" }, new Todo { Id = 4, Title = "Skype with my friend" }, }; public IList<Todo> GetAllToDoItmes() { return _db; } public void AddTodo(Todo item) { _db.Add(item); } public void ToggleTodo(int id) { var todo = _db.FirstOrDefault(x => x.Id == id); todo.Completed = !todo.Completed; } public void DeleteTodo(int id) { var todo = _db.FirstOrDefault(x => x.Id == id); _db.Remove(todo); } } }
در مثال فوق برای نگاشت نام خواص، از System.Text.Json توکار NET Core 3.0. استفاده شدهاست. در ادامه نیز از یک کلاس برای شبیهسازی CRUD یک Todo استفاده شدهاست. سپس برای داشتن اندپوینتهای موردنظر به ازای هر کدام از متدهای فوق درون متد Main، از app.Map... استفاده کردهایم:
using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using todoAPI.Models; namespace todoAPI { class Program { private static readonly TodoData db = new TodoData(); static async Task Main(string[] args) { var app = WebApplication.Create(args); app.MapGet("/", GetTodos); app.MapPost("/api/todos", CreateTodo); app.MapPost("/api/todos/{id}", ToggleTodo); app.MapDelete("/api/todos/{id}", DeleteTodo); await app.RunAsync(); } static async Task GetTodos(HttpContext http) { var todos = db.GetAllToDoItmes(); await http.Response.WriteJsonAsync(todos); } static async Task CreateTodo(HttpContext http) { var todo = await http.Request.ReadJsonAsync<Todo>(); db.AddTodo(todo); http.Response.StatusCode = 204; } static async Task ToggleTodo(HttpContext http) { if (!http.Request.RouteValues.TryGet("id", out int id)) { http.Response.StatusCode = 400; return; } db.ToggleTodo(id); http.Response.StatusCode = 204; } static async Task DeleteTodo(HttpContext http) { if (!http.Request.RouteValues.TryGet("id", out int id)) { http.Response.StatusCode = 400; return; } db.DeleteTodo(id); http.Response.StatusCode = 204; } } }
هر کدام از اندپوینتهای فوق، یک ورودی HttpContext دریافت خواهند کرد. توسط این شیء میتوانیم به درخواست جاری و همچنین به پاسخ درخواست، دسترسی داشته باشیم.
استفاده از سیستم DI توکار NET Core.
همانطور که در ابتدای مطلب نیز عنوان شد، Feather HTTP یک wrapper بر روی APIهای موجود ASP.NET Core است، بنابراین میتوانیم از همان سرویس DI که درون پروژههای ASP.NET Core در اختیار داریم در اینجا نیز استفاده کنیم. در ادامه یک پوشهی جدید را به مثال قبل، با نام Controllers اضافه خواهیم کرد و درون آن یک فایل TodoController را با محتویات زیر ایجاد خواهیم کرد:
using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using todoAPI.Models; using todoAPI.Services; namespace todoAPI.Controllers { public class TodoController { private readonly ITodoService _todoService; public TodoController(ITodoService todoService) { _todoService = todoService; } public async Task GetTodos(HttpContext http) { var todos = _todoService.GetAllToDoItmes(); await http.Response.WriteJsonAsync(todos); } public async Task CreateTodo(HttpContext http) { var todo = await http.Request.ReadJsonAsync<Todo>(); _todoService.AddTodo(todo); http.Response.StatusCode = 204; } public async Task ToggleTodo(HttpContext http) { if (!http.Request.RouteValues.TryGet("id", out int id)) { http.Response.StatusCode = 400; return; } _todoService.ToggleTodo(id); http.Response.StatusCode = 204; } public async Task DeleteTodo(HttpContext http) { if (!http.Request.RouteValues.TryGet("id", out int id)) { http.Response.StatusCode = 400; return; } _todoService.DeleteTodo(id); http.Response.StatusCode = 204; } } }
کاری که انجام شده است، انتقال تمامی متدهای static به کلاس فوق و سپس جایگزین کردن کلمهی کلیدی static با public است. همچنین یه ارجاع به اینترفیس جدید با عنوان ITodoService اضافه شده است؛ درون پیادهسازی این اینترفیس همان متدهای کلاس TodoData را اضافه کردهایم:
using System.Collections.Generic; using todoAPI.Models; using System.Linq; namespace todoAPI.Services { public interface ITodoService { void AddTodo(Todo item); void DeleteTodo(int id); IList<Todo> GetAllToDoItmes(); void ToggleTodo(int id); } public class TodoService : ITodoService { private readonly IList<Todo> _db = new List<Todo> { new Todo { Id = 1, Title = "Read book" }, new Todo { Id = 2, Title = "Watch an episode of Dark" }, new Todo { Id = 3, Title = "Publish a post on dotnettips" }, new Todo { Id = 4, Title = "Skype with my friend" }, }; public IList<Todo> GetAllToDoItmes() { return _db; } public void AddTodo(Todo item) { _db.Add(item); } public void ToggleTodo(int id) { var todo = _db.FirstOrDefault(x => x.Id == id); todo.Completed = !todo.Completed; } public void DeleteTodo(int id) { var todo = _db.FirstOrDefault(x => x.Id == id); _db.Remove(todo); } } }
نکته: برای ایجاد اینترفیس از روی یک کلاس درون VS Code میتوانیم اینگونه عمل کنیم:
تغییرات فایل Program.cs
ابتدا باید using مربوط به DI را در ابتدای فایل اضافه کنیم:
using Microsoft.Extensions.DependencyInjection;
سپس توسط ServiceProvider یک وهله از کلاس موردنظر را ایجاد کردهایم و همچنین سرویسهای موردنظر را درون DI Container اضافه کردهایم:
using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using todoAPI.Controllers; using todoAPI.Services; namespace todoAPI { class Program { static async Task Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddTransient<TodoController>(); builder.Services.AddTransient<ITodoService, TodoService>(); var serviceProvider = builder.Services.BuildServiceProvider(); var todoController = serviceProvider.GetService<TodoController>(); var app = WebApplication.Create(args); app.MapGet("/", todoController.GetTodos); app.MapPost("/api/todos", todoController.CreateTodo); app.MapPost("/api/todos/{id}", todoController.ToggleTodo); app.MapDelete("/api/todos/{id}", todoController.DeleteTodo); await app.RunAsync(); } } }
Convention Over Configuration
در کد قبلی به صورت دستی TodoController را توسط Service Location از DI درخواست کردهایم. اینکار را در ادامه میتوانیم به Feather HTTP سپرده تا کار وهلهسازی را براساس قواعد توکار برایمان انجام دهد:
using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using todoAPI.Services; namespace todoAPI { class Program { static async Task Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); builder.Services.AddControllers(); builder.Services.AddSingleton<ITodoService, TodoService>(); var serviceProvider = builder.Services.BuildServiceProvider(); var app = builder.Build(); app.MapControllers(); await app.RunAsync(); } } }
سپس در ادامه برای دسترسی به HTTP Context درون TodoController از IHttpContextAccessor استفاده کردهایم:
using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using todoAPI.Models; using todoAPI.Services; namespace todoAPI.Controllers { public class TodoController { private readonly ITodoService _todoService; private readonly IHttpContextAccessor _accessor; public TodoController(ITodoService todoService, IHttpContextAccessor accessor) { _todoService = todoService; _accessor = accessor; } [HttpGet("/todos")] public async Task GetTodos() { var todos = _todoService.GetAllToDoItmes(); await _accessor.HttpContext.Response.WriteJsonAsync(todos); } [HttpPost("/todos")] public async Task CreateTodo() { var todo = await _accessor.HttpContext.Request.ReadJsonAsync<Todo>(); _todoService.AddTodo(todo); _accessor.HttpContext.Response.StatusCode = 204; } [HttpPost("/todos/{id}")] public async Task ToggleTodo(int id) { _todoService.ToggleTodo(id); _accessor.HttpContext.Response.StatusCode = 204; } [HttpDelete("/todos/{id}")] public async Task DeleteTodo(int id) { _todoService.DeleteTodo(id); _accessor.HttpContext.Response.StatusCode = 204; } } }
کدهای کامل مطلب را میتوانید از اینجا دریافت کنید.
دوره آموزشی TypeScript در سایت EDX
دوره آموزشی چهار ساعته Blazor Hybrid
Learn Blazor Hybrid - Full Course for Beginners | Build cross-platform apps in C#
Let's start our journey together to build beautiful native cross-platform apps for iOS, Android, macOS, and Windows with Blazor Hybrid, .NET MAUI, C#, and Visual Studio! In this full workshop, I will walk you through everything you need to know about .NET MAUI and building your very first app. You will learn the basics including how to build user interfaces with Razor, how to show data from the internet, how to navigate between pages and combine .NET MAUI pages with Razor pages, access platform features like geolocation, and theme your app for light theme and dark theme. This course has everything you need to learn the basics and set you up for success when building apps with Blazor Hybrid!
Chapters:
00:00:00 - Intro to the Blazor Hybrid Workshop
00:04:28 - What is Blazor Hybrid & How to Install
00:06:51 - First Blazor Hybrid App & Architecture
00:21:40 - Get Code to Build Your First Blazor Hybrid App
00:26:38 - Blazor Hybrid Project Walkthrough
00:39:22 - Start to Build First Blazor Hybrid App
01:03:10 - Event Handling, Data Binding and Parameters (Slides)
01:09:00 - Add Monkey Data & Fluent UI Blazor Components
01:32:08 - Navigation, NavigationManager, .NET MAUI Pages (Slides)
01:39:19 - Navigation with NavigationManager
01:52:39 - Navigation with NavLinks
01:57:21 - Add .NET MAUI Pages & Components
02:21:11 - Access Platform Functionality (Slides)
02:27:57 - Check Network Connectivity
02:38:04 - Get User Location with Geolocation
02:49:09 - Integration with Other Apps
02:57:42 - App Theming, Light Theme, Dark Theme (Slides)
03:05:36 - JavaScript Interoperability with IJSRuntime
03:20:48 - Theming FluentUI Blazor Components
03:26:05 - Style Status Bar with .NET MAUI Community Toolkit
03:39:00 - .NET MAUI Light & Dark Theme with AppThemeBinding
03:42:58 - Sharing State & Creating Reusable Components (Slides)
03:47:27 - Implement Shared State Blazor Hybrid & .NET MAUI
04:02:47 - Create Reusable Razor Components
04:08:31 - CONGRATULATIONS!