مطالب
تزریق مستقیم وابستگی‌ها در Action Method ها و Handler Method های ASP.NET Core
همانطور که میدانید  ASP.NET Core از تزریق وابستگی‌ها ( Dependency Injection ) پشتیبانی میکند، که یک نوع Design Pattern است، و در اصل یک تکنیک است برای دستیابی و پیاده سازی اصل Inversion Of Control یا همان IoC بین کلاس‌ها و وابستگی‌های آن کلاس‌ها. متد ConfigureServices در کلاس Startup وظیفه‌ای دارد برای ثبت و تعریف سرویس‌های مورد استفاده‌ی در برنامه از جمله Platform Features مانند EF Core و معماری MVC. این متد در اصل DI Container ما است و میتوانیم از آن برای loosely coupled کردن برنامه مان از آن استفاده کنیم. در این متد 3 روش برای ثبت و تعریف سرویس‌های ما وجود دارد، که این 3 روش در اصل طول عمر ( حیات ) یک سرویس را مشخص میکنند. در پایین نام این سه LifeTime را برای شما لیست میکنم:
  1. Transient
  2. Scoped
  3. Singleton

تزریق وابستگی را در برنامه‌های ASP.NET Core میتوان به چند طریق انجام داد:
  1. Constructor Injection
  2. Property Injection
  3. Method Injection
  4. Action  & Handler Injection
که بیشترین نوع استفاده از طریق سازنده‌ی کلاس یا همان Constructor است ( نوع اول ).

در این مقاله میخواهیم مورد چهارم را مورد بررسی قرار دهیم، که برای تزریق مستقیم وابستگی به یک Handler Method یا Action Method استفاده میشود؛ بدون تزریق وابستگی به سازنده و ساخت فیلد خصوصی و readonly از Abstraction مورد نظر. مایکروسافت این نوع تزریق را به صورت یک Attribute در آورده است، که از کلاس Attribute هم ارث بری کرده است و در فضای نام
Microsoft.AspNetCore.Mvc
قرار گرفته است و نام آن FromServices است. برای بررسی اجمالی این کلاس میتوانید به لینک رو به رو مراجعه کنید. FromServicesAttribute Class  

خب نحوه استفاده از این Attribute را در ادامه یاد خواهیم گرفت. همانطور که در بالا گفته شد، با استفاده از این صفت دیگر نیازی به تزریق وابستگی در سازنده ندارید؛ البته از این صفت مواقعی استفاده میشود که برای مثال فقط در یک اکشن متد یا هندلر متد میخواهید استفاده کنید.
مثال واقعی:
فرض کنید که یک Controller دارید همراه با 15 عدد Action Method، یا یک Razor Page دارید که در PageModel آن چند Handler Method دارید، حالا نیاز به یک سرویسی دارید که در تمامی این Handler Method‌ها یا Action Method‌ها باید استفاده شود، مانند کلاس Context که برای EF Core است. حالا فرض کنید یکی از آن 15 کنترلرها نیاز به یک سرویس خاصی دارد، مثلا سرویس ارسال ایمیل، و در 14 تای دیگر این سرویس استفاده نمیشود، پس اینجا منطقی است که تزریق وابستگی به صورت مستقیم در خود Action Method انجام بگیرد. در مثال پایین میبینید که اینترفیس IEmailSender را در اکشن متد به صورت مستقیم تزریق کرده‌ایم، بدون دخالت سازنده کلاس. البته این Abstraction باید یک کلاس پیاده سازی کننده داشته باشد و در DI Container پروژه به ثبت رسیده باشد.
مثال شماره 1:
 public class AccountController : Controller
    {
        public IActionResult ConfirmEmail([FromServices] IEmailSender emailSender)
        {
           // emailSender.SendAsync(...);
        }
    }

مثال شماره 2:
public IActionResult About([FromServices] IDateTime dateTime)
{
    ViewData["Message"] = $"Current server time: {dateTime.Now}";

    return View();
}

مثال شماره 3:
[HttpGet]
 public ProductModel GetProduct([FromServices] IProductModelRequestService productModelRequest)
 {
     return productModelRequest.Value;
 }
از این صفت میتوانید در Handler Method‌های Razor Page‌ها هم استفاده کنید و هیچ محدودیتی در استفاده از آن‌ها در صفحات قدرتمند Razor وجود ندارد.
اشتراک‌ها
فریمورک تهیه شده با Asp.net Mvc و Asp.net Web Api به صورت NTier با پشتیبانی از چند زبانگی

These are some key features of the framework itself:

Modular and NLayered architecture
Multi-tenancy
Dependency Injection
Domain Driven Design
Unit of work implementation
Flexible Localization system
Automatic data filters
Audit logging
Setting management
Menu management
Authorization
Exception handling
Validation
Logging
Event bus for domain events
Auto-creating Web API layer for Application Services
Auto-creating Javascript proxy layer to use Web API layer
Javascript helper methods for ajax, notifications, message boxes, making UI busy...
Easily working with embedded resources
Useful extension and helper methods   

فریمورک تهیه شده با Asp.net Mvc و Asp.net Web Api به صورت NTier با پشتیبانی از چند زبانگی
اشتراک‌ها
بررسی اکوسیستم React در سال 2024

As React celebrates its 11th anniversary in 2024, it’s worth looking ahead to the exciting developments in the React ecosystem. In this blog, we’ll explore various aspects of the ecosystem, building on what was happening in 2023 and what you can expect in the coming year. 

بررسی اکوسیستم React در سال 2024
اشتراک‌ها
جلسه پرسش و پاسخ در مورد آینده‌ی ASP.NET Core و Blazor

ASP.NET Core and Blazor futures Q&A | DIS201H

#MSBuild

Join us for a discussion on the future of web development with the ASP.NET Core team. Get the team's perspective first-hand on the roadmap for ASP.NET Core and Blazor in .NET 8 and get all of your burning questions answered. We discuss Blazor, Native AOT, cloud native development, and anything else that you want to ask us about. 

جلسه پرسش و پاسخ در مورد آینده‌ی ASP.NET Core و Blazor
مطالب
مدیریت طول عمر DbContext در برنامه‌های Blazor SSR

فرض کنید یک صفحه‌ی Blazor SSR، از سه کامپوننت منوی سمت راست، محتوای اصلی صفحه و فوتر سایت که به همراه متنی است، تشکیل شده‌است. منوی سمت راست، به همراه لینک‌هایی‌است که آمار آن‌ها را نیز نمایش می‌دهد و این اطلاعات را از بانک اطلاعاتی، به کمک EF-Core دریافت می‌کند. فوتر صفحه، سال شروع به کار و نام برنامه را از بانک اطلاعاتی دریافت می‌کند و محتوای اصلی صفحه نیز از بانک اطلاعاتی دریافت می‌شود. پس از تکمیل این سه کامپوننت مجزا، اگر برنامه را اجرا کنید، بلافاصله با خطای زیر مواجه می‌شوید:

A second operation started on this context before a previous operation completed

مشکل کجاست؟! مشکل اینجاست که تنها یک نمونه از DbContext، در طول درخواست جاری رسیده، بین سه کامپوننت جاری برنامه به اشتراک گذاشته می‌شود (به سازنده‌ی سرویس‌های مرتبط تزریق می‌شود) و ... در Blazor SSR، پردازش کامپوننت‌های یک صفحه، به صورت موازی و همزمان انجام می‌شوند؛ یعنی ترتیبی نیست. اگر ابتدا کامپوننت منو، بعد محتوای صفحه و در آخر فوتر، رندر می‌شدند، هیچگاه پیام فوق را مشاهده نمی‌کردیم؛ اما ... هر سه کامپوننت، با هم و همزمان رندر می‌شوند و سپس نتیجه‌ی نهایی در Response درج خواهد شد. یعنی یک DbContext بین چندین ترد به اشتراک گذاشته می‌شود که چنین حالتی توسط EF-Core پشتیبانی نمی‌شود و مجاز نیست.

روش مواجه شدن با یک چنین حالت‌هایی، نمونه سازی مجزای DbContext به ازای هر کامپوننت است که نمونه‌ای از آن‌را پیشتر در مطلب «نکات ویژه‌ی کار با EF-Core در برنامه‌های Blazor Server» مشاهده کرده‌اید. در این مطلب، راه‌حل دیگری برای اینکار ارائه می‌شود که ساده‌تر است و نیازی به تغییرات آنچنانی در کدهای کامپوننت‌ها و کل برنامه ندارد.

استفاده از کلاس پایه‌ی OwningComponentBase برای نمونه سازی مجدد DbContext به‌ازای هر کامپوننت

زمانیکه در برنامه‌های Blazor SSR از روش استاندارد زیر برای دسترسی به سرویس‌های مختلف برنامه استفاده می‌کنیم:

@inject IHotelRoomService HotelRoomService

طول عمر دریافتی سرویس، دقیقا بر اساس طول عمر اصلی تعریف شده‌ی آن عمل می‌کند (شبیه به برنامه‌های ASP.NET Core). یعنی برای مثال اگر Scoped باشد، DbContext تزریق شده‌ی در آن هم Scoped است و این DbContext، بین تمام کامپوننت‌های در حال پردازش موازی در طول یک درخواست، به‌اشتراک گذاشته می‌شود که مطلوب ما نیست. ما می‌خواهیم بتوانیم به ازای هر کامپوننت مجزای صفحه، یک DbContext جدید داشته باشیم. یعنی باید بتوانیم خودمان این سرویس Scoped را نمونه سازی کنیم و نه اینکه آن‌را مستقیما از سیستم تزریق وابستگی‌ها دریافت کنیم.

بنابراین اگر بخواهیم قسمت‌های مختلف برنامه را تغییر ندهیم و همان تعاریف ابتدایی services.AddDbContext و Scoped تعریف کردن سرویس‌های برنامه بدون تغییر باقی بمانند (و از IDbContextFactory و موارد مشابه دیگر مطلب «نکات ویژه‌ی کار با EF-Core در برنامه‌های Blazor Server» هم استفاده نکنیم)، باید جایگزینی را برای نمونه سازی سرویس‌ها ارائه دهیم. به همین جهت در ابتدا، یک ویژگی جدیدی را به صورت زیر تعریف می‌کنیم:

[AttributeUsage(AttributeTargets.Property)]
public sealed class InjectComponentScopedAttribute : Attribute
{
}

تا بتوانیم بجای:

@inject IHotelRoomService HotelRoomService

بنویسیم:

[InjectComponentScoped] internal IHotelRoomService HotelRoomService { set; get; } = null!;

مرحله‌ی بعد، نوبت به نمونه سازی خودکار این سرویس‌های درخواستی علامتگذاری شده‌ی با InjectComponentScoped است. برای این منظور، تمام کامپوننت‌های برنامه را از کلاس پایه و استاندارد OwningComponentBase ارث‌بری می‌کنیم. مزیت اینکار، امکان دسترسی به خاصیتی به نام ScopedServices در تمام کامپوننت‌های برنامه است که توسط آن می‌توان به متد ScopedServices.GetRequiredService آن دسترسی یافت. یعنی با ارث‌بری از کلاس پایه‌ی OwningComponentBase به ازای هر کامپوننت، به صورت خودکار Scope جدیدی شروع می‌شود که توسط آن می‌توان به نمونه‌ی جدیدی از سرویس مدنظر دسترسی یافت و نه به نمونه‌ی اشتراکی در طی درخواست جاری.

اکنون اگر از این مزیت به صورت زیر استفاده کنیم، می‌توان تمام سرویس‌های درخواستی مزین به InjectComponentScopedAttribute یک کامپوننت را به صورت خودکار یافته و با استفاده از ScopedServices.GetRequiredService، مقدار دهی کرد:

public class BlazorScopedComponentBase : OwningComponentBase
{
    private static readonly ConcurrentDictionary<Type, Lazy<List<PropertyInfo>>> CachedProperties = new();

    private List<PropertyInfo> InjectComponentScopedPropertiesList => CachedProperties.GetOrAdd(GetType(),
            type => new Lazy<List<PropertyInfo>>(
                () => type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance |
                                         BindingFlags.NonPublic | BindingFlags.Public)
                    .Where(p => p.GetCustomAttribute<InjectComponentScopedAttribute>() is not null)
                    .ToList(), LazyThreadSafetyMode.ExecutionAndPublication)).Value;

    protected override void OnInitialized()
    {
        foreach (var propertyInfo in InjectComponentScopedPropertiesList)
        {
            propertyInfo.SetValue(this, ScopedServices.GetRequiredService(propertyInfo.PropertyType));
        }
    }
}

این سرویس، اینبار طول عمری، محدود به کامپوننت جاری را خواهد داشت و بین سایر کامپوننت‌های درحال پردازش درخواست جاری، به اشتراک گذاشته نمی‌شود و همچنین به صورت خودکار هم در پایان درخواست، Dispose می‌شود.

فعالسازی ارث‌بری خودکار در تمام کامپوننت‌های برنامه

مرحله‌ی بعد، ارث‌بری خودکار تمام کامپوننت‌های برنامه از OwningComponentBase سفارشی فوق است و در اینجا قصد نداریم تمام کامپوننت‌ها را جهت معرفی آن، به صورت دستی تغییر دهیم. برای اینکار فقط کافی است به فایل Imports.razor_ مراجعه و یک سطر زیر را در آن درج کنیم:

@inherits BlazorScopedComponentBase

با اینکار یک ارث‌بری سراسری در کل برنامه رخ می‌دهد و تمام کامپوننت‌ها، از BlazorScopedComponentBase مشتق خواهند شد. یعنی پس از این تغییر، اگر سرویسی را به صورت زیر معرفی و با ویژگی InjectComponentScoped علامتگذاری کردیم:

[InjectComponentScoped] internal IHotelRoomService HotelRoomService { set; get; } = null!;

به صورت خودکار یافت شده و نمونه سازی Scoped محدود به طول عمر همان کامپوننت می‌شود که بین سایر کامپوننت‌ها، به اشتراک گذاشته نخواهد شد.

یک نکته: اگر کامپوننت شما متد OnInitialized را بازنویسی می‌کند، ‌فراموش نکنید که در ابتدای آن باید ()base.OnInitialized را هم فراخوانی کنید تا متد OnInitialized کامپوننت پایه‌ی BlazorScopedComponentBase نیز فراخوانی شود. البته این مورد در حین بازنویسی نمونه‌ی async آن مهم نیست؛ چون همیشه OnInitialized غیر async در ابتدا فراخوانی می‌شود و سپس نمونه‌ی async آن اجرا خواهد شد.

اشتراک‌ها
چگونه برنامه تحت دسکتاپ خود را به تحت NET Core 3.0. تبدیل کنید

In this post, I will describe how to port a desktop application from .NET Framework to .NET Core. I picked a WinForms application as an example. Steps for WPF application are similar and I’ll describe what needs to be done different for WPF as we go. I will also show how you can keep using the WinForms designer in Visual Studio even though it is under development and is not yet available for .NET Core projects. 

چگونه برنامه تحت دسکتاپ خود را به تحت NET Core 3.0. تبدیل کنید
اشتراک‌ها
API نویسی اصولی و حرفه ای در ASP.NET Core

Professional REST API design with ASP.NET Core and WebAPI

This project is an example of lightweight and extensible infrastructure for building RESTful Web API with ASP.NET Core.

This example contains a number of tricks and techniques which I've learned while building APIs in ASP.NET Core.

Techniques and Features

  •  JWT Authentication
  • Secure JWT using Encryption (JWE)
  • Logging to File, Console and Database using Elmah & NLog
  • Logging to sentry.io (Log Management System)
  • Exception Handling using Custom Middleware
  • Automatic Validation
  • Standard API Resulting
  • Dependency Injection using Autofac
  • Map resources using AutoMapper
  • Async/Await Best Practices
  • Versioning Management
  • Using Swagger (Swashbuckle)
  • Auto Document Generator for Swagger
  • Integrate Swagger and Versioning
  • Integrate Swagger and JWT/OAuth Authentication
  • Best Practices for Performance and Security 
API نویسی اصولی و حرفه ای در ASP.NET Core
اشتراک‌ها
کتابخانه unitegallery

The Unite Gallery is multipurpose javascript gallery based on jquery library. It's built with a modular technique with a lot of accent of ease of use and customization. It's very easy to customize the gallery, changing it's skin via css, and even writing your own theme. Yet this gallery is very powerfull, fast and has the most of nowdays must have features like responsiveness, touch enabled and even zoom feature, it's unique effect.  Demo

Features

  • The gallery plays VIDEO from: Youtube, Vimeo, HTML5, Wistia and SoundCloud (not a video but still )
  • Responsive - fits to every screen with automatic ratio preserve
  • Touch Enabled - Every gallery parts can be controlled by the touch on touch enabled devices
  • Responsive - The gallery can fit every screen size, and can respond to a screen size change.
  • Skinnable - Allow to change skin with ease in different css file without touching main gallery css.
  • Themable - The gallery has various of themes, each theme has it's own options and features, but it uses gallery core objects
  • Zoom Effect - The gallery has unique zoom effect that could be applied within buttons, mouse wheel or pinch gesture on touch - enabled devices
  • Gallery Buttons - The gallery has buttons on it, like full screen or play/pause that optimized for touch devidces access
  • Keyboard controls - The gallery could be controlled by keyboard (left, right arrows)
  • Tons of options. The gallery has huge amount of options for every gallery object that make the customization process easy and fun.
  • Powerfull API - using the gallery API you can integrate the gallery into your website behaviour and use it with another items like lightboxes etc.
کتابخانه unitegallery