JSON Web Token is a security token which acts as a container for claims about the user, it can be transmitted easily between the Authorization server (Token Issuer), and the Resource server (Audience), the claims in JWT are encoded using JSON which make it easier to use especially in applications built using JavaScript.
اگر بخواهیم بر روی سرور خودمان راه اندازی کنیم چه راه حلی وجود دارد ؟
یک سناریوی فرضی را در نظر بگیرید. اگر بخواهیم IdentityDbContext و دیگر DbContextهای اپلیکیشن را ادغام کنیم چه باید کرد؟ مثلا یک سیستم وبلاگ که برخی کاربران میتوانند پست جدید ثبت کنند، برخی تنها میتوانند کامنت بگذارند و تمامی کاربران هم اختیارات مشخص دیگری دارند. در چنین سیستمی شناسه کاربران (User ID) در بسیاری از مدلها (موجودیتها و مدلهای اپلیکیشن) وجود خواهد داشت تا مشخص شود هر رکورد به کدام کاربر متعلق است. در این مقاله چنین سناریو هایی را بررسی میکنیم و best practiceهای مربوطه را مرور میکنیم.
پس از ورود به سایت بعنوان یک مدیر، میتوانید ToDoهای ثبت شده توسط تمام کاربران را مشاهده کنید.
در این پست یک اپلیکیشن ساده ToDo خواهیم ساخت که امکان تخصیص to-doها به کاربران را نیز فراهم میکند. در این مثال خواهیم دید که چگونه میتوان مدلهای مختص به سیستم عضویت (IdentityDbContext) را با مدلهای دیگر اپلیکیشن مخلوط و استفاده کنیم.
تعریف نیازمندیهای اپلیکیشن
- تنها کاربران احراز هویت شده قادر خواهند بود تا لیست ToDoهای خود را ببینند، آیتمهای جدید ثبت کنند یا دادههای قبلی را ویرایش و حذف کنند.
- کاربران نباید آیتمهای ایجاد شده توسط دیگر کاربران را ببینند.
- تنها کاربرانی که به نقش Admin تعلق دارند باید بتوانند تمام ToDoهای ایجاد شده را ببینند.
پس بگذارید ببینیم چگونه میشود اپلیکیشنی با ASP.NET Identity ساخت که پاسخگوی این نیازمندیها باشد.
ابتدا یک پروژه ASP.NET MVC جدید با مدل احراز هویت Individual User Accounts بسازید. در این اپلیکیشن کاربران قادر خواهند بود تا بصورت محلی در وب سایت ثبت نام کنند و یا با تامین کنندگان دیگری مانند گوگل و فیسبوک وارد سایت شوند. برای ساده نگاه داشتن این پست ما از حسابهای کاربری محلی استفاده میکنیم.
در مرحله بعد ASP.NET Identity را راه اندازی کنید تا بتوانیم نقش مدیر و یک کاربر جدید بسازیم. میتوانید با اجرای اپلیکیشن راه اندازی اولیه را انجام دهید. از آنجا که سیستم ASP.NET Identity توسط Entity Framework مدیریت میشود میتوانید از تنظیمات پیکربندی Code First برای راه اندازی دیتابیس خود استفاده کنید.
در قدم بعدی راه انداز دیتابیس را در Global.asax تعریف کنید.
Database.SetInitializer<MyDbContext>(new MyDbInitializer());
ایجاد نقش مدیر و کاربر جدیدی که به این نقش تعلق دارد
اگر به قطعه کد زیر دقت کنید، میبینید که در خط شماره 5 متغیری از نوع UserManager ساخته ایم که امکان اجرای عملیات گوناگونی روی کاربران را فراهم میکند. مانند ایجاد، ویرایش، حذف و اعتبارسنجی کاربران. این کلاس که متعلق به سیستم ASP.NET Identity است همتای SQLMembershipProvider در ASP.NET 2.0 است.
در خط 6 یک RoleManager میسازیم که امکان کار با نقشها را فراهم میکند. این کلاس همتای SQLRoleMembershipProvider در ASP.NET 2.0 است.
در این مثال نام کلاس کاربران (موجودیت کاربر در IdentityDbContext) برابر با "MyUser" است، اما نام پیش فرض در قالبهای پروژه VS 2013 برابر با "ApplicationUser" میباشد.
public class MyDbInitializer : DropCreateDatabaseAlways<MyDbContext> { protected override void Seed(MyDbContext context) { var UserManager = new UserManager<MyUser>(new UserStore<MyUser>(context)); var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context)); string name = "Admin"; string password = "123456"; //Create Role Admin if it does not exist if (!RoleManager.RoleExists(name)) { var roleresult = RoleManager.Create(new IdentityRole(name)); } //Create User=Admin with password=123456 var user = new MyUser(); user.UserName = name; var adminresult = UserManager.Create(user, password); //Add User Admin to Role Admin if (adminresult.Succeeded) { var result = UserManager.AddToRole(user.Id, name); } base.Seed(context); } }
حال فایلی با نام Models/AppModels.cs بسازید و مدل EF Code First اپلیکیشن را تعریف کنید. از آنجا که از EF استفاده میکنیم، روابط کلیدها بین کاربران و ToDoها بصورت خودکار برقرار میشود.
public class MyUser : IdentityUser { public string HomeTown { get; set; } public virtual ICollection<ToDo> ToDoes { get; set; } } public class ToDo { public int Id { get; set; } public string Description { get; set; } public bool IsDone { get; set; } public virtual MyUser User { get; set; } }
در قدم بعدی با استفاده از مکانیزم Scaffolding کنترلر جدیدی بهمراه تمام Viewها و متدهای لازم برای عملیات CRUD بسازید. برای اطلاعات بیشتر درباره نحوه استفاده از مکانیزم Scaffolding به این لینک مراجعه کنید.
لطفا دقت کنید که از DbContext فعلی استفاده کنید. این کار مدیریت دادههای Identity و اپلیکیشن شما را یکپارچهتر میکند. DbContext شما باید چیزی شبیه به کد زیر باشد.
public class MyDbContext : IdentityDbContext<MyUser> { public MyDbContext() : base("DefaultConnection") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { public System.Data.Entity.DbSet<AspnetIdentitySample.Models.ToDo> ToDoes { get; set; } }
تنها کاربران احراز هویت شده باید قادر به اجرای عملیات CRUD باشند
برای این مورد از خاصیت Authorize استفاده خواهیم کرد که در MVC 4 هم وجود داشت. برای اطلاعات بیشتر لطفا به این لینک مراجعه کنید.
[Authorize] public class ToDoController : Controller
کنترلر ایجاد شده را ویرایش کنید تا کاربران را به ToDoها اختصاص دهد. در این مثال تنها اکشن متدهای Create و List را بررسی خواهیم کرد. با دنبال کردن همین روش میتوانید متدهای Edit و Delete را هم بسادگی تکمیل کنید.
یک متد constructor جدید بنویسید که آبجکتی از نوع UserManager میپذیرد. با استفاده از این کلاس میتوانید کاربران را در ASP.NET Identity مدیریت کنید.
private MyDbContext db; private UserManager<MyUser> manager; public ToDoController() { db = new MyDbContext(); manager = new UserManager<MyUser>(new UserStore<MyUser>(db)); }
اکشن متد Create را بروز رسانی کنید
هنگامی که یک ToDo جدید ایجاد میکنید، کاربر جاری را در ASP.NET Identity پیدا میکنیم و او را به ToDoها اختصاص میدهیم.
public async Task<ActionResult> Create ([Bind(Include="Id,Description,IsDone")] ToDo todo) { var currentUser = await manager.FindByIdAsync (User.Identity.GetUserId()); if (ModelState.IsValid) { todo.User = currentUser; db.ToDoes.Add(todo); await db.SaveChangesAsync(); return RedirectToAction("Index"); } return View(todo); }
اکشن متد List را بروز رسانی کنید
در این متد تنها ToDoهای کاربر جاری را باید بگیریم.
public ActionResult Index() { var currentUser = manager.FindById(User.Identity.GetUserId()); return View(db.ToDoes.ToList().Where( todo => todo.User.Id == currentUser.Id)); }
تنها مدیران سایت باید بتوانند تمام ToDoها را ببینند
بدین منظور ما یک اکشن متد جدید به کنترل مربوطه اضافه میکنیم که تمام ToDoها را لیست میکند. اما دسترسی به این متد را تنها برای کاربرانی که در نقش مدیر وجود دارند میسر میکنیم.
[Authorize(Roles="Admin")] public async Task<ActionResult> All() { return View(await db.ToDoes.ToListAsync()); }
نمایش جزئیات کاربران از جدول ToDo ها
از آنجا که ما کاربران را به ToDo هایشان مرتبط میکنیم، دسترسی به دادههای کاربر ساده است. مثلا در متدی که مدیر سایت تمام آیتمها را لیست میکند میتوانیم به اطلاعات پروفایل تک تک کاربران دسترسی داشته باشیم و آنها را در نمای خود بگنجانیم. در این مثال تنها یک فیلد بنام HomeTown اضافه شده است، که آن را در کنار اطلاعات ToDo نمایش میدهیم.
@model IEnumerable<AspnetIdentitySample.Models.ToDo> @{ ViewBag.Title = "Index"; } <h2>List of ToDoes for all Users</h2> <p> Notice that we can see the User info (UserName) and profile info such as HomeTown for the user as well. This was possible because we associated the User object with a ToDo object and hence we can get this rich behavior. 12: </p> <table class="table"> <tr> <th> @Html.DisplayNameFor(model => model.Description) </th> <th> @Html.DisplayNameFor(model => model.IsDone) </th> <th>@Html.DisplayNameFor(model => model.User.UserName)</th> <th>@Html.DisplayNameFor(model => model.User.HomeTown)</th> </tr> 25: 26: @foreach (var item in Model) 27: { 28: <tr> 29: <td> 30: @Html.DisplayFor(modelItem => item.Description) 31: </td> 32: <td> @Html.DisplayFor(modelItem => item.IsDone) </td> <td> @Html.DisplayFor(modelItem => item.User.UserName) </td> <td> @Html.DisplayFor(modelItem => item.User.HomeTown) </td> </tr> } </table>
صفحه Layout را بروز رسانی کنید تا به ToDoها لینک شود
<li>@Html.ActionLink("ToDo", "Index", "ToDo")</li> <li>@Html.ActionLink("ToDo for User In Role Admin", "All", "ToDo")</li>
حال اپلیکیشن را اجرا کنید. همانطور که مشاهده میکنید دو لینک جدید به منوی سایت اضافه شده اند.
ساخت یک ToDo بعنوان کاربر عادی
روی لینک ToDo کلیک کنید، باید به صفحه ورود هدایت شوید چرا که دسترسی تنها برای کاربران احراز هویت شده تعریف وجود دارد. میتوانید یک حساب کاربری محلی ساخته، با آن وارد سایت شوید و یک ToDo بسازید.
پس از ساختن یک ToDo میتوانید لیست رکوردهای خود را مشاهده کنید. دقت داشته باشید که رکوردهایی که کاربران دیگر ثبت کرده اند برای شما نمایش داده نخواهند شد.
مشاهده تمام ToDoها بعنوان مدیر سایت
روی لینک ToDoes for User in Role Admin کلیک کنید. در این مرحله باید مجددا به صفحه ورود هدایت شوید چرا که شما در نقش مدیر نیستید و دسترسی کافی برای مشاهده صفحه مورد نظر را ندارید. از سایت خارج شوید و توسط حساب کاربری مدیری که هنگام راه اندازی اولیه دیتابیس ساخته اید وارد سایت شوید.
User = Admin Password = 123456
من میخواهم IDP خودمون رو با کمک is4 مستقر کنم. مشکل اینه که سامانهها و نرم افزارهایی هستند که خودمون ننوشتیم و نمینویسیم، بلکه توسط پیمانکاران مختلف (با معماریهای مختلف) طراحی شدن و هر کدوم بصورت جزیره ای (احراز هویت مستقل دارن ولی مثلا کد ملی بین همه مشترکه) دارن کار میکنن با یوزرهای خودشون. میخواهیم در نهایت بهشون یک فایل راهنما بدیم که طبق اون دستورالعمل (و بر اساس client id , client secret خودشون)، هرکدوم از اونها به idp ما، متصل بشن جهت احراز هویت و گرفتن اطلاعات اصلی کاربران (مباحث کانورت اطلاعات و حواشی اینچنین رو کار ندارم و فرض میکنیم مشکلی نیست)
1: با توجه به اینکه IS4 بر اساس openid connect + oauth2 پیاده سازی شده و مورد تایید هم میباشد و بر اساس ارسال درخواستها روی front channel و back channel هست، آیا محدودیت هایی برای تنوع بسترهای مختلف بعنوان کلاینت هست یا خیر؟
مثلا برای
php, oracle adf, asp.net web forms, asp.net mvc, ...
2: چه مقدار تغییرات خواهند داشت؟ فقط روال ورود و خروج رو باید تغییر بدن؟ با توجه به اینکه مثلا روال user, role, user-role کلاسیک خودشون رو دارن جهت authorization لوکال منابع داخلیشون
3: ما فقط میخواهیم از is4 بعنوان مخزن مشترک " اطلاعات اصلی" کاربران و درگاه ورود/خروج مشترک استفاده کنیم. یعنی :
- در ابتدا کاربر میاد به idp و رجیستر میکنه تا بتونه از سامانههای مختلف متصل به idp استفاده کنه
- کاربر جهت لاگین در کلاینت (سامانه)، هدایت میشه به idp (این کار توسط همون کلاینت انجام میشه)
- بعد از احراز هویت در idp، کاربر ریدایرکت میشه به همون برنامه (کلاینت)
- حالا وقتی برمیگرده به کلاینت، اون برنامه، "اطلاعات اصلی" کاربر (که از idp برگشته) رو داره
- کاربر رو در دیتابیس لوکال خودش جستجو میکنه (مثلا بر اساس subject_id)؛ یا پیداش میکنه و یا اگه کاربر در دیتابیس لوکال اون سامانه وجود نداشته باشه، بعنوان کاربر جدید درجش میکنه
- با کاربر مرحله قبل، در سامانه لوکال لاگین میکنه
- دیگه برنامه لوکال (کلاینت) با idp کاری نداره. چون سیاست داخلی خودش رو داره جهت هندل کردن sessionها و دسترسیها بر اساس roleهای لوکال در اون برنامه. تا زمانی که بخواد کاربر logout کنه.
- برای logout، کاربر در کلاینت لاگ اوت و سپس در سمت idp لاگ اوت میشه و مجددا به homepage سامانه لوکال ریدایرکت میشه
آیا سناریو بالا درسته؟
4: با توجه به توضیحات مطروحه، برای این تنوع کلاینتها که بالاتر عنوان کردم، باید از hybrid flow استفاده کنیم یا authorization code + PKCE؟ یا باز برای هر کلاینت جداگانه بررسی و تصمیم گیری کنیم بسته به نوع مکانیزمش
مسیرراهها
ASP.NET Core
ASP.NET Core 1.0
- قسمت اول: Net Core. چیست؟
- قسمت دوم: بررسی ساختار جدید Solution
- قسمت سوم: Middleware چیست؟
- قسمت چهارم: فعالسازی پردازش فایلهای استاتیک
- قسمت پنجم: فعالسازی صفحات مخصوص توسعه دهنده ها
- قسمت ششم: سرویسها و تزریق وابستگی ها
- قسمت هفتم: کار با فایلهای Config
- قسمت هشتم: فعالسازی ASP.NET MVC
- قسمت نهم: بررسی تغییرات مسیریابی
- قسمت دهم: بررسی تغییرات Viewها
- قسمت یازدهم: بررسی بهبودهای Razor
- قسمت دوازدهم: معرفی Tag Helpers
- قسمت سیزدهم: معرفی View Components
- قسمت چهاردهم: فعال سازی اعتبارسنجی ورودیهای کاربران
- قسمت پانزدهم: بررسی تغییرات Caching
- قسمت شانزدهم:کار با Sessions
- قسمت هفدهم: بررسی فریم ورک Logging
- قسمت هجدهم: کار با ASP.NET Web API
- قسمت نوزدهم: بومی سازی
- قسمت بیستم: بررسی تغییرات فیلترها
- قسمت بیست و یکم: بررسی تغییرات Bundling و Minification
- قسمت بیست و دوم: توزیع برنامه توسط IIS
- پیاده سازی Unobtrusive Ajax در ASP.NET Core 1.0
ASP.NET Core 2.0
- امکان استفادهی مستقیم از کتابخانههای Full .NET Framework در NET Core 2.0.
- Tag Helper Components در ASP.NET Core 2.0
- کار با Razor در ASP.NET Core 2.0
- فعالسازی Windows Authentication در برنامههای ASP.NET Core 2.0
ASP.NET Core 2.1
روش ارتقاء
ASP.NET Core Identity
کار با Areas در ASP.NET Core
کار با کوکیها در ASP.NET Core
بررسی روش آپلود فایلها در ASP.NET Core
ارسال ایمیل در ASP.NET Core
نوشتن Middleware سفارشی در ASP.NET Core
نوشتن TagHelperهای سفارشی برای ASP.NET Core
بررسی تغییرات Reflection در NET Core.
استفادهی گسترده از DateTimeOffset در NET Core.
بررسی روش دسترسی به HttpContext در ASP.NET Core
توزیع پروژههای ASP.NET Core 1.1 بدون ارائه فایلهای View آن
تغییرات رمزنگاری اطلاعات در NET Core.
ساخت بستههای نیوگت مخصوص NET Core.
تهیه قالب برای ارسال ایمیلها در ASP.NET Core توسط Razor Viewها
روش یافتن لیست تمام کنترلرها و اکشن متدهای یک برنامهی ASP.NET Core
بررسی روش آپلود فایلها از طریق یک برنامهی Angular به یک برنامهی ASP.NET Core
سفارشی سازی صفحهی اول برنامههای Angular CLI توسط ASP.NET Core
تغییرات Encoding در NET Core.
ASP.NET Core Identity
- سفارشی سازی
- امکان ساخت قالب برای پروژههای NET Core.
- تبدیل قالبهای سفارشی پروژههای NET Core. به بستههای NuGet
طراحی یک گرید با Angular و ASP.NET Core
- افزودن و اعتبارسنجی خودکار Anti-Forgery Tokens در برنامههای Angular مبتنی بر ASP.NET Core
- تولید هدرهای Content Security Policy توسط ASP.NET Core برای برنامههای Angular
- غیرمعتبر شدن کوکیهای برنامههای ASP.NET Core هاست شدهی در IIS پس از ریاستارت آن
- اعتبارسنجی مبتنی بر JWT در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
- اعتبارسنجی مبتنی بر کوکیها در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
- فعالسازی HSTS در ASP.NET Core
- مراحل تنظیم Let's Encrypt در IIS
- IdentityServer 4x
- قسمت اول - نیاز به تامین کنندهی هویت مرکزی
- قسمت دوم - ایجاد ساختار اولیهی مثال این سری
- قسمت سوم - بررسی مفاهیم OpenID Connect
- قسمت چهارم - نصب و راه اندازی IdentityServer
- قسمت پنجم - پیاده سازی ورود و خروج از سیستم
- قسمت ششم - کار با User Claims
- قسمت هفتم- امن سازی Web API
- قسمت هشتم- تعریف سطوح دسترسی پیچیده
- قسمت نهم- مدیریت طول عمر توکنها
- قسمت دهم- ذخیره سازی اطلاعات کاربران IDP در بانک اطلاعاتی
- قسمت یازدهم- استفاده از تامین کنندههای هویت خارجی
- قسمت دوازدهم- یکپارچه سازی با اکانت گوگل
- قسمت سیزدهم- فعالسازی اعتبارسنجی دو مرحلهای
- قسمت چهاردهم- آماده شدن برای انتشار برنامه
- قسمت اول - نیاز به تامین کنندهی هویت مرکزی
کار با Areas در ASP.NET Core
کار با کوکیها در ASP.NET Core
بررسی روش آپلود فایلها در ASP.NET Core
ارسال ایمیل در ASP.NET Core
نوشتن Middleware سفارشی در ASP.NET Core
نوشتن TagHelperهای سفارشی برای ASP.NET Core
بررسی تغییرات Reflection در NET Core.
استفادهی گسترده از DateTimeOffset در NET Core.
بررسی روش دسترسی به HttpContext در ASP.NET Core
توزیع پروژههای ASP.NET Core 1.1 بدون ارائه فایلهای View آن
تغییرات رمزنگاری اطلاعات در NET Core.
ساخت بستههای نیوگت مخصوص NET Core.
تهیه قالب برای ارسال ایمیلها در ASP.NET Core توسط Razor Viewها
روش یافتن لیست تمام کنترلرها و اکشن متدهای یک برنامهی ASP.NET Core
بررسی روش آپلود فایلها از طریق یک برنامهی Angular به یک برنامهی ASP.NET Core
سفارشی سازی صفحهی اول برنامههای Angular CLI توسط ASP.NET Core
تغییرات Encoding در NET Core.
تغییرات متدهای بازگشت فایلها به سمت کلاینت در ASP.NET Core
پیاده سازی برنامههای چند مستاجری در ASP.NET Core
مقدمهای بر تزریق وابستگیها درASP.NET Core
نمایش خطاهای اعتبارسنجی سمت سرور ASP.NET Core در برنامههای Angular
احراز هویت و اعتبارسنجی کاربران در برنامههای Angular - قسمت اول - معرفی و ایجاد ساختار برنامه
روش استفادهی صحیح از HttpClient در برنامههای دات نت
اجرای سرویسهای NodeJS در ASP.NET Core
بررسی خطاهای ممکن در حین راه اندازی اولیه برنامههای ASP.NET Core در IIS
تست کردن متدهای یک Controller به کمک PowerShell
کار با Visual Studio در ASP.NET Core
پیاده سازی برنامههای چند مستاجری در ASP.NET Core
مقدمهای بر تزریق وابستگیها درASP.NET Core
نمایش خطاهای اعتبارسنجی سمت سرور ASP.NET Core در برنامههای Angular
احراز هویت و اعتبارسنجی کاربران در برنامههای Angular - قسمت اول - معرفی و ایجاد ساختار برنامه
روش استفادهی صحیح از HttpClient در برنامههای دات نت
اجرای سرویسهای NodeJS در ASP.NET Core
بررسی خطاهای ممکن در حین راه اندازی اولیه برنامههای ASP.NET Core در IIS
تست کردن متدهای یک Controller به کمک PowerShell
کار با Visual Studio در ASP.NET Core
تسکهای پس زمینه (Background Job) چیست؟
بطور کلی تسکهای پس زمینه، کارهایی هستند که برنامه باید بصورت خودکار در زمانهای مشخصی آنها را انجام دهد؛ برای مثال شرایطی را در نظر بگیرید که متدی را با حجم زیادی از محاسبات پیچیده دارید که وقتی کاربر درخواست خود را ارسال میکند، شروع به محاسبه میشود و کاربر چارهای جز انتظار نخواهد داشت؛ اما اگر اینکار در زمانی دیگر، قبل از درخواست کاربر محاسبه میشد و صرفا نتیجهاش به کاربر نمایش داده میشد، قطعا تصمیم گیری بهتری نسبت به محاسبهی آنی آن متد، در زمان درخواست کاربر بوده.
در سناریوی دیگری تصور کنید میخواهید هر شب در ساعتی مشخص، خلاصهای از مطالب وبسایتتان را برای کاربران وبسایت ایمیل کنید. در این حالت برنامه باید هر شب در ساعتی خاص اینکار را برای ما انجام دهد و تماما باید این اتفاق بدون دخالت هیچ ارادهی انسانی و بصورت خودکار توسط برنامه انجام گیرد.
همچنین شرایطی از این قبیل، ارسال ایمیل تایید هویت، یک ساعت بعد از ثبت نام، گرفتن بک آپ از اطلاعات برنامه بصورت هفتگی و دیگر این موارد، همه در دستهی تسکهای پس زمینه (Background Job) از یک برنامه قرار دارند.
سؤال : HangFire چیست؟
همانطور که دانستید، تسکهای پس زمینه نیاز به یک سیستم مدیریت زمان دارند که کارها را در زمانهای مشخص شدهای به انجام برساند. HangFire یک پکیج متن باز، برای ایجاد سیستم زمانبندی شدهی کارها است و اینکار را به سادهترین روش، انجام خواهد داد. همچنین HangFire در کنار Quartz که سیستم دیگری جهت پیاده سازی زمانبندی است، از معروفترین پکیجها برای زمانبندی تسکهای پس زمینه بشمار میروند که در ادامه بیشتر به مزایا و معایب این دو میپردازیم.
مقایسه HangFire و Quartz
میتوان گفت این دو پکیج تا حد زیادی شبیه به هم هستند و تفاوت اصلی آنها، در لایههای زیرین و نوع محاسبات زمانی هریک، نهفته است که الگوریتم مختص به خود را برای این محاسبات دارند؛ اما در نهایت یک کار را انجام میدهند.
دیتابیس :
تفاوتی که میتوان از آن نام برد، وجود قابلیت Redis Store در HangFire است که Quratz چنین قابلیتی را از سمت خودش ارائه نداده و برای استفاده از Redis در Quartz باید شخصا این دو را باهم کانفیگ کنید. دیتابیس Redis بخاطر ساختار دیتابیسی که دارد، سرعت و پرفرمنس بالاتری را ارائه میدهد که استفاده از این قابلیت، در پروژههایی با تعداد تسکها و رکوردهای زیاد، کاملا مشهود است. البته این ویژگی در HangFire رایگان نیست و برای داشتن آن از سمت HangFire، لازم است هزینهی آن را نیز پرداخت کنید؛ اما اگر هم نمیخواهید پولی بابتش بپردازید و همچنان از آن استفاده کنید، یک پکیج سورس باز برای آن نیز طراحی شده که از این لینک میتوانید آنرا مشاهده کنید.
ساختار :
پکیج HangFire از ابتدا با دات نت و معماریهای دات نتی توسعه داده شده، اما Quartz ابتدا برای زبان جاوا نوشته شده بود و به نوعی از این زبان، ریلیزی برای دات نت تهیه شد و این موضوع طبعا تاثیرات خودش را داشته و برخی از معماریها و تفکرات جاوایی در آن مشهود است که البته مشکلی را ایجاد نمیکند و محدودیتی نسبت به HangFire از لحاظ کارکرد، دارا نیست. شاید تنها چیزی که میتوان در این باب گفت، DotNet Friendlyتر بودن HangFire است که کار با متدهای آن، آسانتر و به اصطلاح، خوش دستتر است.
داشبورد :
هردو پکیج از داشبورد، پشتیبانی میکنند که میتوانید در این داشبورد و ui اختصاصی که برای نمایش تسکها طراحی شده، تسکهای ایجاد شده را مدیریت کنید. داشبورد HangFire بصورت پیشفرض همراه با آن قرار دارد که بعد از نصب HangFire میتوانید براحتی داشبورد سوار بر آن را نیز مشاهده کنید. اما در Quartz ، داشبورد باید بصورت یک Extension، در پکیجی جدا به آن اضافه شود و مورد استفاده قرار گیرد. در لینکهای 1 و 2، دوتا از بهترین داشبوردها برای Quartz را مشاهده میکنید که در صورت نیاز میتوانید از آنها استفاده کنید.
استفاده از HangFire
1. نصب :
- برای نصب HangFire در یک پروژهی Asp.Net Core لازم است ابتدا پکیجهای مورد نیاز آن را نصب کنید؛ که شامل موارد زیر است:
Install-Package Hangfire.Core Install-Package Hangfire.SqlServer Install-Package Hangfire.AspNetCore
- پس از نصب پکیجها باید تنظیمات مورد نیاز برای پیاده سازی HangFire را در برنامه، اعمال کنیم. این تنظیمات شامل افزودن سرویسها و اینترفیسهای HangFire به برنامه است که اینکار را با افزودن HangFire به متد ConfigureService کلاس Startup انجام خواهیم داد:
public void ConfigureServices(IServiceCollection services) { // Add Hangfire services. services.AddHangfire(configuration => configuration .SetDataCompatibilityLevel(CompatibilityLevel.Version_170) .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() .UseSqlServerStorage(Configuration.GetConnectionString("HangfireConnection"), new SqlServerStorageOptions { CommandBatchMaxTimeout = TimeSpan.FromMinutes(5), SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5), QueuePollInterval = TimeSpan.Zero, UseRecommendedIsolationLevel = true, DisableGlobalLocks = true })); // Add the processing server as IHostedService services.AddHangfireServer(); // Add framework services. services.AddMvc(); }
- پکیج HangFire برای مدیریت کار و زمان ، Table هایی دارد که پس از نصب، بر روی دیتابیس برنامهی شما قرار میگیرد. فقط باید دقت داشته باشید ConnectionString دیتابیس خود را در متد AddHangFire مقدار دهی کنید، تا از این طریق دیتابیس برنامه را شناخته و Tableهای مورد نظر را در Schema جدیدی با نام HangFire به آن اضافه کند.
پ ن : HangFire بصورت پیشفرض با دیتابیس SqlServer ارتباط برقرار میکند.
- این پکیج یک داشبورد اختصاصی دارد که در آن لیستی از انواع تسکهای در صف انجام و گزارشی از انجام شدهها را در اختیار ما قرار میدهد. برای تنظیم این داشبورد باید Middleware مربوط به آن و endpoint جدیدی را برای شناسایی مسیر داشبورد HangFire در برنامه، در متد Configure کلاس Startup اضافه کنید :
public void Configure(IApplicationBuilder app, IBackgroundJobClient backgroundJobs, IHostingEnvironment env) { // HangFire Dashboard app.UseHangfireDashboard(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); // HangFire Dashboard endpoint endpoints.MapHangfireDashboard(); }); }
برای اینکه به داشبورد HangFire دسترسی داشته باشید، کافیست پس از نصب و انجام تنظیمات مذکور، برنامه را اجرا کنید و در انتهای Url برنامه، کلمهی "hangfire" را وارد کنید. سپس وارد پنل داشبورد آن خواهید شد.
http://localhost:50255/hangfire
app.UseHangfireDashboard("/mydashboard");
http://localhost:50255/mydashboard
2. داشبورد :
داشبورد HangFire شامل چندین بخش و تب مختلف است که به اختصار هر یک را بررسی خواهیم کرد.
تب Job :
همهی تسکهای تعریف شده، شامل Enqueued, Succeeded, Processing, Failed و... در این تب نشان داده میشوند.
تب Retries :
این تب مربوط به تسکهایی است که در روال زمانبندی و اجرا، به دلایل مختلفی مثل Stop شدن برنامه توسط iis یا Down شدن سرور و یا هر عامل خارجی دیگری، شکست خوردند و در زمانبندی مشخص شده، اجرا نشدند. همچنین قابلیت دوبارهی به جریان انداختن job مورد نظر را در اختیار ما قرار میدهد که از این طریق میتوان تسکهای از دست رفته را مدیریت کرد و دوباره انجام داد.
تب Recurring Jobs :
وقتی شما یک تسک را مانند گرفتن بکاپ از دیتابیس، بصورت ماهانه تعریف میکنید و قرار است در هر ماه، این اتفاق رخ دهد، این مورد یک تسک تکراری تلقی شده و این تب مسئول نشان دادن اینگونه از تسکها میباشد.
تب Servers :
این بخش، سرویسهایی را که HangFire برای محاسبهی زمانبندی از آنها استفاده میکند، نشان میدهد. وقتی متد services.AddHangfireServer را به متد ConfigureService کلاس Startup اضافه میکنید، سرویسهای HangFire جهت محاسبهی زمانبندیها فعال میشوند.
3. امنیت داشبورد :
همانطور که دانستید، داشبورد، اطلاعات کاملی از نوع کارها و زمان اجرای آنها و نام متدها را در اختیار ما قرار میدهد و همچنین اجازهی تغییراتی را مثل حذف یک تسک، یا دوباره به اجرا در آوردن تسکها و یا اجرای سریع تسکهای به موعد نرسیده را به کاربر میدهد. گاهی ممکن است این اطلاعات، شامل محتوایی امنیتی و غیر عمومی باشد که هرکسی در برنامه حق دسترسی به آنها را ندارد. برای مدیریت کردن این امر، میتوانید مراحل زیر را طی کنید :
مرحله اول : یک کلاس را ایجاد میکنیم (مثلا با نام MyAuthorizationFilter) که این کلاس از اینترفیسی با نام IDashboardAuthorizationFilter ارث بری خواهد کرد.
public class MyAuthorizationFilter : IDashboardAuthorizationFilter { public bool Authorize(DashboardContext context) { var httpContext = context.GetHttpContext(); // Allow all authenticated users to see the Dashboard (potentially dangerous). return httpContext.User.Identity.IsAuthenticated; } }
درون این کلاس، متدی با نام Authorize از اینترفیس مربوطه، پیاده سازی میشود که شروط احراز هویت و صدور یا عدم صدور دسترسی را کنترل میکند. این متد، یک خروجی Boolean دارد که اگر هر یک از شروط احراز هویت شما تایید نشد، خروجی false را بر میگرداند. در این مثال، ما برای دسترسی، محدودیت Login بودن را اعمال کردهایم که این را از HttpContext میگیریم.
مرحله دوم : در این مرحله کلاسی را که بعنوان فیلتر احراز هویت برای کاربران ساختهایم، در optionهای middleware پکیج HangFire اضافه میکنیم.
app.UseHangfireDashboard("/hangfire", new DashboardOptions { Authorization = new [] { new MyAuthorizationFilter() } });
app.UseHangfireDashboard("/hangfire", new DashboardOptions { IsReadOnlyFunc = (DashboardContext context) => true });
این گزینه اجازهی هرگونه تغییری را در روند تسکها، از طریق صفحهی داشبورد، از هر کاربری سلب میکند و داشبورد را صرفا به جهت نمایش کارها استفاده میکند نه چیز دیگر.
انواع تسکها در HangFire :
1. تسکهای Fire-And-Forget :
تسکهای Fire-And-Forget زمانبندی خاصی ندارند و بلافاصله بعد از فراخوانی، اجرا میشوند. برای مثال شرایطی را در نظر بگیرید که میخواهید پس از ثبت نام هر کاربر در وبسایت، یک ایمیل خوش آمد گویی ارسال کنید. این عمل یک تسک پس زمینه تلقی میشود، اما زمانبندی خاصی را نیز نمیخواهید برایش در نظر بگیرید. در چنین شرایطی میتوانید از متد Enqueue استفاده کنید و یک تسک Fire-And-Forget را ایجاد کنید تا این تسک صرفا در تسکهای پس زمینهتان نام برده شود و قابل مشاهده باشد.
public class HomeController : Controller { private readonly IBackgroundJobClient _backgroundJobClient; public HomeController(IBackgroundJobClient backgroundJobClient) { _backgroundJobClient = backgroundJobClient; } [HttpPost] [Route("welcome")] public IActionResult Welcome(string userName) { var jobId = _backgroundJobClient.Enqueue(() => SendWelcomeMail(userName)); return Ok($"Job Id {jobId} Completed. Welcome Mail Sent!"); } public void SendWelcomeMail(string userName) { //Logic to Mail the user Console.WriteLine($"Welcome to our application, {userName}"); } }
2. تسکهای Delayed :
همانطور که از اسم آن پیداست، تسکهای Delayed، تسکهایی هستند که با یک تاخیر در زمان، اجرا خواهند شد. بطور کلی زمانبندی این تسکها به دو دسته تقسیم میشود :
- دسته اول : اجرا پس از تاخیر در زمانی مشخص.
همان شرایط ارسال ایمیل را به کاربرانی که در وبسایتتان ثبت نام میکنند، در نظر بگیرید؛ اما اینبار میخواهید نه بلافاصله، بلکه 10 دقیقه بعد از ثبت نام کاربر، ایمیل خوش آمد گویی را ارسال کنید. در این نوع شما یک تاخیر 10 دقیقهای میخواهید که Delayed Jobها اینکار را برای ما انجام میدهند.
public class HomeController : Controller { private readonly IBackgroundJobClient _backgroundJobClient; public HomeController(IBackgroundJobClient backgroundJobClient) { _backgroundJobClient = backgroundJobClient; } [HttpPost] [Route("welcome")] public IActionResult Welcome(string userName) { var jobId = BackgroundJob.Schedule(() => SendWelcomeMail(userName),TimeSpan.FromMinutes(10)); return Ok($"Job Id {jobId} Completed. Welcome Mail Sent!"); } public void SendWelcomeMail(string userName) { //Logic to Mail the user Console.WriteLine($"Welcome to our application, {userName}"); } }
همچنین میتوانید از ورودیهای دیگر نوع TimeSpan شامل TimeSpan.FromMilliseconds و TimeSpan.FromSecondsو TimeSpan.FromMinutes و TimeSpan.FromDays برای تنظیم تاخیر در تسکهای خود استفاده کنید.
- دسته دوم : اجرا در زمانی مشخص.
نوع دیگر استفاده از متد Schedule، تنظیم یک تاریخ و زمان مشخصی برای اجرا شدن تسکهای در آن تاریخ و زمان واحد میباشد. برای مثال سناریویی را در نظر بگیرید که دستور اجرا و زمانبندی آن، در اختیار کاربر باشد و کاربر بخواهد یک Reminder، در تاریخ مشخصی برایش ارسال شود که در اینصوررت میتوانید با استفاده از instance دیگری از متد Schedule که ورودی ای از جنس DateTimeOffset را دریافت میکند، تاریخ مشخصی را برای آن اجرا، انتخاب کنید.
public class HomeController : Controller { private readonly IBackgroundJobClient _backgroundJobClient; public HomeController(IBackgroundJobClient backgroundJobClient) { _backgroundJobClient = IBackgroundJobClient; } [HttpPost] [Route("welcome")] public IActionResult Welcome(string userName , DateTime dateAndTime) { var jobId = BackgroundJob.Schedule(() => SendWelcomeMail(userName),DateTimeOffset(dateAndTime)); return Ok($"Job Id {jobId} Completed. Welcome Mail Sent!"); } public void SendWelcomeMail(string userName) { //Logic to Mail the user Console.WriteLine($"Welcome to our application, {userName}"); } }
در این مثال، تاریخ مشخصی را برای اجرای تسکهای خود، از کاربر، در ورودی اکشن متد دریافت کردهایم و به متد Schedule، در غالب DateTimeOffset تعریف شده، پاس میدهیم.
3. تسکهای Recurring :
تسکهای Recurring به تسکهایی گفته میشود که باید در یک بازهی گردشی از زمان اجرا شوند. در یک مثال، بیشتر با آن آشنا خواهیم شد. فرض کنید میخواهید هر هفته، برنامه از اطلاعات دیتابیس موجود بکاپ بگیرد. در اینجا تسکی را دارید که قرار است هر هفته و هربار به تکرر اجرا شود.
public class HomeController : Controller { private readonly IRecurringJobManager _recurringJobManager; public HomeController(IRecurringJobManager recurringJobManager) { _recurringJobManager = recurringJobManager; } [HttpPost] [Route("BackUp")] public IActionResult BackUp(string userName) { _recurringJobManager.AddOrUpdate("test", () => BackUpDataBase(), Cron.Weekly); return Ok(); } public void BackUpDataBase() { // ... } }
برای تنظیم یک Recurring Job باید اینترفیس دیگری را بنام IRecurringJobManager، تزریق کرده و متد AddOrUpdate را استفاده کنید. در ورودی این متد، یک نوع تعریف شده در HangFire بنام Cron دریافت میشود که بازهی گردش در زمان را دریافت میکند که در اینجا بصورت هفتگی است.
انواع دیگر Cron شامل :
- هر دقیقه (Cron.Minutely) :
این Cron هر دقیقه یکبار اجرا خواهد شد.
_recurringJobManager.AddOrUpdate("test", () => job , Cron.Minutely);
- هر ساعت (Cron.Hourly) :
این Cron هر یک ساعت یکبار و بصورت پیشفرض در دقیقه اول هر ساعت اجرا میشود.
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Hourly);
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Hourly(10));
- هر روز (Cron.Daily) :
این Cron بصورت روزانه و در حالت پیشفرض، در اولین ساعت و اولین دقیقهی هر روز اجرا خواهد شد.
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Daily);
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Daily(3,10));
- هر هفته (Cron.Weekly) :
این Cron هفتگی است. بصورت پیشفرض هر هفته، شنبه در اولین ساعت و در اولین دقیقه، اجرا میشود.
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Weekly);
_recurringJobManager.AddOrUpdate("test", () => Job,Cron.Weekly(DayOfWeek.Monday,3,10));
- هر ماه (Cron.Monthly) :
این Cron بصورت ماهانه اولین روز ماه در اولین ساعت روز و در اولین دقیقه ساعت، زمانبندی خود را اعمال میکند.
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Monthly);
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Monthly(10,3,10));
- هر سال (Cron.Yearly) :
و در نهایت این Cron بصورت سالانه و در اولین ماه، روز، ساعت و دقیقه هر سال، وظیفه خود را انجام خواهد داد.
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Yearly);
_recurringJobManager.AddOrUpdate("test", () => Job, Cron.Yearly(2,4,3,10));
در نهایت با استفاده از این Cronها میتوانید انواع مختلفی از Recurring Jobها را بسازید.
4. تسکهای Continuations :
این نوع از تسکها، وابسته به تسکهای دیگری هستند و بطور کلی وقتی استفاده میشوند که ما میخواهیم تسکی را پس از تسک دیگری، با یک زمانبندی، به نسبت زمان اجرای تسک اول، اجرا کنیم. برای مثال میخواهیم 10 دقیقه بعد از ثبت نام کاربر، برای او ایمیل احراز هویت ارسال شود که شبیه اینکار را در تسکهای Delayed انجام داده بودیم. اما همچنین قصد داریم 5 دقیقه بعد از ارسال ایمیل احراز هویت، لینک فرستاده شده را منسوخ کنیم. در این سناریو ما دو زمانبندی داریم؛ اول 10 دقیقه بعد از ثبت نام کاربر و دوم 5 دقیقه بعد از اجرای متد اول.
var stepOne = _backgroundJobClient.Schedule(() => SendAuthorizationEmail(), TimeSpan.FromMinute(10)); _backgroundJobClient.ContinueJobWith(stepOne, () => _backgroundJobClient.Schedule(() => ExpireAuthorizationEmail(), TimeSpan.FromHours(5)));
برای ایجاد یک Continuations Job باید از متد ContinueJobWith در اینترفیس IBackgroundJobClient استفاده کنیم و در ورودی اول این متد، آیدی تسک ایجاد شده قبلی را پاس دهیم.
برخی از نکات و ترفندهای HangFire
1. استفاده از Cron Expression در Recurring Jobها :
بطور کلی، Cron، ساختاری تعریف شده برای تعیین بازههای زمانی است. Cron اختصار یافتهی کلمات Command Run On میباشد که به اجرا شدن یک دستور، در زمان مشخصی اشاره دارد. برای استفاده از آن، ابتدا به تعریف این ساختار میپردازیم :
* * * * * command to be executed - - - - - | | | | | | | | | ----- Day of week (0 - 7) (Sunday=0 or 7) | | | ------- Month (1 - 12) | | --------- Day of month (1 - 31) | ----------- Hour (0 - 23) ------------- Minute (0 - 59)
* * * * *
- فیلد اول (Minute) : در این فیلد باید دقیقهای مشخص از یک ساعت را وارد کنید؛ مانند دقیقه 10 (میتوانید محدودهای را هم تعیین کنید)
- فیلد دوم (Hour) : در این فیلد باید زمان معلومی را با فرمت ساعت وارد کنید؛ مانند ساعت 7 (میتوانید محدودهای را هم تعیین کنید، مانند ساعات 12-7)
- فیلد سوم (Day of Month) : در این فیلد باید یک روز از ماه را وارد کنید؛ مانند روز 15 ام از ماه (میتوانید محدودهای را هم تعیین کنید)
- فیلد چهارم (Month) : در این فیلد باید یک ماه از سال را وارد کنید؛ مثلا ماه 4 ام(آوریل) (میتوانید محدودهای را هم تعیین کنید)
- فیلد پنجم (Day of Week) : در این فیلد باید روزی از روزهای هفته یا محدودهای از آن روزها را تعیین کنید. مانند صفرم هفته که در کشورهای اروپایی و آمریکایی معادل روز یکشنبه است.
همانطور که میبینید، Cronها دسترسی بهتری از تعیین بازههای زمانی مختلف را ارائه میدهند که میتوانید از آن در Recurring متدها بجای ورودیهای Yearly - Monthly - Weekly - Daily - Hourly - Minutely استفاده کنید. در واقع خود این ورودیها نیز متدی تعریف شده در کلاس Cron هستند که با فراخوانی آن، خروجی Cron Expression را میسازند و در درون ورودی متد Recurring قرار میگیرند.
در ادامه مثالی را خواهیم زد تا نیازمندی به Cron Expressionها را بیشتر درک کنید. فرض کنید میخواهید یک زمانبندی داشته باشید که "هر ماه بین بازه 10 ام تا 15 ام، بطور روزانه در ساعت 4:00" اجرا شود. اعمال این زمانبندی با متدهای معمول در کلاس Cron امکان پذیر نیست؛ اما میتوانید با Cron Expression آنرا اعمال کنید که به این شکل خواهد بود:
0 4 10-15 * *
برای ساخت Cron Expressionها وبسایت هایی وجود دارند که کمک میکنند انواع Cron Expressionهای پیچیدهای را طراحی کنیم و با استفاده از آن، زمانبندیهای دقیقتر و جزئیتری را بسازیم. یکی از بهترین وبسایتها برای اینکار crontab.guru است.
پ. ن. برای استفاده از Cron Expression در متدهای Recurring کافی است بجای ورودیهای Yearly - Monthly - Weekly - Daily - Hourly - Minutely ، خود Cron Expression را درون ورودی متد تعریف کنیم :
_recurringJobManager.AddOrUpdate("test", () => job , "0 4 10-15 * *" );
2. متد Trigger :
متد Trigger یک متد برای اجرای آنی تسکهای Recurring است که به کمک آن میتوانید این نوع از تسکها را بدون در نظر گرفتن زمانبندی آنها، در لحظه اجرا کنید و البته تاثیری در دفعات بعدی تکرار نداشته باشد.
RecurringJob.Trigger("some-id");
3. تعیین تاریخ انقضاء برای Recurring Jobها :
گاهی ممکن است در تسکهای Recurring شرایطی پیش آید که برفرض میخواهید کاری را هر ماه انجام دهید، اما این تکرار در پایان همان سال تمام میشود. در اینصورت باید یک Expire Time برای متد Recurring خود تنظیم کنیم تا بعد از 12 ماه تکرار، در تاریخ 140X/12/30 به پایان برسد. HangFire برای متدهای Recurring ورودی با عنوان ExpireTime تعریف نکرده، اما میتوان از طریق ایجاد یک زمانبندی، تاریخ مشخصی را برای حذف کردن متد Recurring تعریف کرد که همانند یک ExpireTime عمل میکند.
_recurringJobManager.AddOrUpdate("test", () => Console.WriteLine("Recurring Job"), Cron.Monthly); _backgroundJobClient.Schedule(() => _recurringJobManager.RemoveIfExists("test"), DateTimeOffset(dateAndTime));
با اجرای این متد، اول کاری برای تکرار در زمانبندی ماهیانه ایجاد میشود و در متد دوم، زمانی برای حذف متد اول مشخص میکند.
در آخر امیدوارم این مقاله برایتان مفید واقع شده باشد. میتوانید فیدبکتان را در قالب کامنت یا یک قهوه برایم ارسال کنید.
مسیرراهها
Blazor 5x
مبانی Blazor
- قسمت 4 : بخش 1 - Data Binding
- قسمت 5 : بخش 2 - کامپوننتها
- قسمت 6 : بخش 3 - چرخههای حیات کامپوننتها
- قسمت 7 : بخش 4 - انتقال اطلاعات از کامپوننتهای فرزند به کامپوننت والد
- قسمت 8 : بخش 5 - تامین محتوای نمایشی کامپوننتهای فرزند توسط کامپوننت والد
- قسمت 9 : بخش 6 - ساده سازی تعاریف ویژگیهای المانها و انتقال پارامترها به چندین زیر سطح
- قسمت 10 : بخش 7 - مسیریابی
- قسمت 11 : بخش 8 - کار با جاوا اسکریپت
- قسمت 12 : بخش 9 - یک تمرین
کار با فرمها
- قسمت 13 : بخش 1 - کار با EF Core در برنامههای Blazor Server
- قسمت 14 : بخش 2 - تعریف فرمها و اعتبارسنجی آنها
- قسمت 15 : بخش 3 - ویرایش اطلاعات
- قسمت 16 : بخش 4 - تهیه سرویسهای آپلود تصاویر
- قسمت 17 : بخش 5 - آپلود تصاویر
- قسمت 18 : بخش 6 - حذف اطلاعات
- قسمت 19 : بخش 7 - نکات ویژهی کار با EF-Core در برنامههای Blazor Server
- قسمت 20 : بخش 8 - استفاده از یک کامپوننت ثالث HTML Editor
احراز هویت و اعتبارسنجی کاربران Blazor Server
- قسمت 21 : بخش 1 - افزودن قالب ابتدایی Identity
- قسمت 22 : بخش 2 - ورود به سیستم و خروج از آن
- قسمت 23 : بخش 3 - کار با نقشهای کاربران
تهیه API مخصوص Blazor WASM
Blazor WASM
- قسمت 26 : ایجاد و تنظیمات اولیه
- قسمت 27 : کار با سرویسهای Web API
- قسمت 28 : نمایش لیست اطلاعات دریافتی از Web API
- قسمت 29 : یک تمرین: رزرو کردن یک اتاق انتخابی
- قسمت 30 : افزودن پرداخت آنلاین توسط درگاه مجازی پرباد
احراز هویت و اعتبارسنجی کاربران Blazor WASM
- قسمت 31 : بخش 1 - انجام تنظیمات اولیه
- قسمت 32 : بخش 2 - ثبت نام، ورود به سیستم و خروج از آن
- قسمت 33 : بخش 3 - بهبود تجربهی کاربری عدم دسترسیها
- پیاده سازی سیاستهای دسترسی پویای سمت سرور و کلاینت در برنامههای Blazor WASM
توزیع برنامه
مدیریت استثناءها
بررسی تغییرات Blazor 8x
- قسمت اول : معرفی SSR
- قسمت دوم : بررسی حالت رندر سمت سرور
- قسمت سوم : روش ارتقاء برنامههای Blazor Server قدیمی به دات نت 8
- قسمت چهارم : معرفی فرمهای جدید تعاملی
- قسمت پنجم : امکان تعریف جزیرههای تعاملی Blazor Server
- قسمت ششم : نکات تکمیلی ویژگی راهبری بهبود یافتهی صفحات SSR
- قسمت هفتم : امکان تعریف جزیرههای تعاملی Blazor WASM
- قسمت هشتم : مدیریت انتقال اطلاعات Pre-Rendering سمت سرور، به جزایر تعاملی
- قسمت نهم : معرفی حالت رندر تعاملی خودکار
- قسمت دهم : مدیریت حالت کاربران در روشهای مختلف رندر
- قسمت یازدهم : قالب جدید پیاده سازی اعتبارسنجی و احراز هویت - بخش اول
- قسمت دوازدهم : قالب جدید پیاده سازی اعتبارسنجی و احراز هویت - بخش دوم
- قسمت سیزدهم : امکان تعریف Sections
- قسمت چهاردهم : امکان استفاده از کامپوننتهای Blazor در برنامههای ASP.NET Core 8x
مطالب تکمیلی
- Best practiceهای یک پروژه Blazor
- کامپوننتهای جنریک در Blazor
- مدیریت حالت در برنامههای Blazor توسط الگوی Observer - قسمت اول
- مدیریت حالت در برنامههای Blazor توسط الگوی Observer - قسمت دوم
- روش آپلود فایلها به همراه اطلاعات یک مدل در برنامههای Blazor WASM 5x
- دریافت و نمایش فایلهای PDF در برنامههای Blazor WASM
- ارسال خطاهای رخدادهی در برنامههای سمت کلاینت Blazor WASM، به تلگرام
- بهبود کارآیی نمایش لیستها در Blazor با استفاده از دایرکتیو key@
- معرفی Blazor Hybrid
- امکان استفاده از کتابخانههای native در Blazor WASM 6x
- امکان ساخت برنامههای دسکتاپ چندسکویی Blazor در دات نت 6
- حل مشکل بارگذاری اولیه دستورات جاوا اسکریپتی در پروژههای Blazor
- پیاده سازی Remote Validation در Blazor
- روش ایجاد پروژههای کتابخانهای کامپوننتهای Blazor
- استفاده از date picker شمسی جاوا اسکریپتی در Blazor با قابلیت ورود تاریخ به صورت دستی
- ارائهی قالبی عمومی برای استفاده از تقویمهای جاوااسکریپتی در Blazor
- بهبود صفحهی بارگذاری اولیه در Blazor WASM
- استفاده از چند دکمه با عملکردهای مختلف برای ارسال یک EditForm در Blazor
- دستیابی به HttpContext در Blazor Server
- جلوگیری از دوباره اجرا شدن ناخواستهی متدهای نامتقارن در Blazor
- نکات ویژه کار با عملیات نامتقارن در Blazor Server
- استفاده از لنگر (anchor) برای اسکرول به قسمت خاصی از صفحه در Blazor Server
پیاده سازی سمت کلاینت مستقلی دارد. دو سری مطلب در این مورد در سایت تا به امروز داریم؛ از آنها ایده بگیرید:
نظرات مطالب
روش یکی کردن پروژههای React و ASP.NET Core
در پروژه ای قصد دارم فقط صفحه ای خاص رو با react طراحی کنم و بقیه صفحات توسط razor پیاده سازی شد است دست نخورده باقی بماند.
در این صورت نحوه احراز هویت این صفحه به چه صورت است ؟
نحوه خواندن cookieهای پروژه در react به چه صورت امکان پذیر است ؟
در این صورت نحوه احراز هویت این صفحه به چه صورت است ؟
نحوه خواندن cookieهای پروژه در react به چه صورت امکان پذیر است ؟