The first version of ASP.NET was released 17 years ago and during these years, it is fascinating to see how the ASP.NET team constructively reacted through these years to the major shifts happening on the web. Initially a platform that was closed and tried to hide and abstract the web; ASP.NET has metamorphized into an open source and cross platform - one that fully embraces the nature of the web. This is the first part of a series of 3 articles that will cover the history of ASP.NET from its launch to the latest ASP.NET Core releases.
تغییرات Web API در دات نت 8
Preview 3 of .NET 8 includes a new project templates to create an API with a TODO service instead of the weather forecast . Looking into the generated code of this template, there are a lot more changes going on such as a slim builder and using a JSON source generator which helps when using AOT to create native .NET binaries. This article looks into the changes coming.
ایجاد یک پروژهی ابتدایی Blazor WASM
پروژهای را که در این مطلب تکمیل خواهیم کرد، از نوع Blazor WASM هاست شدهاست. بنابراین در پوشهی فرضی BlazorAsyncValidation، دستور «dotnet new blazorwasm --hosted» را صادر میکنیم تا ساختار ابتدایی پروژه که به همراه یک کلاینت Blazor WASM و یک سرور ASP.NET Core Web API است، تشکیل شود. از قسمت Web API، برای پیاده سازی اعتبارسنجی سمت سرور استفاده خواهیم کرد.
مدل ثبت نام برنامه
مدل ثبت نام برنامه تنها از یک خاصیت نام تشکیل شده و در پروژهی Shared قرار میگیرد تا هم در کلاینت و هم در سرور قابل استفاده باشد:
using System.ComponentModel.DataAnnotations; namespace BlazorAsyncValidation.Shared; public class UserDto { [Required] public string Name { set; get; } = default!; }
کنترلر API ثبت نام برنامه
کنترلر زیر که در پوشهی BlazorAsyncValidation\Server\Controllers قرار میگیرد، منطق بررسی تکراری نبودن نام دریافتی از برنامهی کلاینت را شبیه به منطق remote validation استاندارد MVC، پیاده سازی میکند که در نهایت یک true و یا false را باز میگرداند.
در اینجا خروجی بازگشت داده کاملا در اختیار شما است و نیازی نیست تا حتما ارتباطی با MVC داشته باشد؛ چون مدیریت سمت کلاینت بررسی آنرا خودمان انجام خواهیم داد و نه یک کتابخانهی از پیش نوشته شده و مشخص.
using BlazorAsyncValidation.Shared; using Microsoft.AspNetCore.Mvc; namespace BlazorAsyncValidation.Server.Controllers; [ApiController, Route("api/[controller]/[action]")] public class RegisterController : ControllerBase { [HttpPost] public IActionResult IsUserNameUnique([FromBody] UserDto userModel) { if (string.Equals(userModel?.Name, "Vahid", StringComparison.OrdinalIgnoreCase)) { return Ok(false); } return Ok(true); } }
غنی سازی فرم استاندارد Blazor جهت انجام Remote validation
اگر بخواهیم از EditForm استاندارد Blazor در حالت متداول آن و بدون هیچ تغییری استفاده کنیم، مانند مثال زیر که InputText متصل به خاصیت Name مربوط به Dto برنامه را نمایش میدهد:
@page "/" <PageTitle>Index</PageTitle> <h2>Register</h2> <EditForm EditContext="@EditContext" OnValidSubmit="DoSubmitAsync"> <DataAnnotationsValidator/> <div class="row mb-2"> <label class="col-form-label col-lg-2">Name:</label> <div class="col-lg-10"> <InputText @bind-Value="Model.Name" class="form-control"/> <ValidationMessage For="@(() => Model.Name)"/> </div> </div> <button class="btn btn-secondary" type="submit">Submit</button> </EditForm>
public partial class Index { private const string UserValidationUrl = "/api/Register/IsUserNameUnique"; private ValidationMessageStore? _messageStore; [Inject] private HttpClient HttpClient { set; get; } = default!; private EditContext? EditContext { set; get; } private UserDto Model { get; } = new();
ValidationMessageStore به همراه متد Add است و اگر به آن نام فیلد مدنظر را به همراه پیامی، اضافه کنیم، این اطلاعات را به صورت خطای اعتبارسنجی توسط کامپوننت ValidationMessage نمایش میدهد.
محل مقدار دهی اولیهی این اشیاء نیز در روال رویدادگردان OnInitialized به صورت زیر است:
protected override void OnInitialized() { EditContext = new EditContext(Model); _messageStore = new ValidationMessageStore(EditContext); EditContext.OnFieldChanged += (sender, eventArgs) => { var fieldIdentifier = eventArgs.FieldIdentifier; _messageStore?.Clear(fieldIdentifier); _ = InvokeAsync(async () => { var errors = await OnValidateFieldAsync(fieldIdentifier.FieldName); if (errors?.Any() != true) { return; } foreach (var error in errors) { _messageStore?.Add(fieldIdentifier, error); } EditContext.NotifyValidationStateChanged(); }); StateHasChanged(); }; EditContext.OnValidationStateChanged += (sender, eventArgs) => StateHasChanged(); EditContext.OnValidationRequested += (sender, eventArgs) => _messageStore?.Clear(); }
برای مثال اگر فیلدی تغییر کند، رویداد OnFieldChanged صادر میشود. در همینجا است که کار فراخوانی متد OnValidateFieldAsync که در ادامه معرفی میشود را انجام میدهیم تا کار اعتبارسنجی Async سمت سرور را انجام دهد. اگر نتیجهای به همراه آن بود، توسط messageStore به صورت یک خطای اعتبارسنجی نمایش داده خواهد شد و همچنین EditContext نیز با فراخوانی متد NotifyValidationStateChanged، وادار به بهروز رسانی وضعیت اعتبارسنجی خود میگردد.
متد سفارشی OnValidateFieldAsync که کار اعتبارسنجی سمت سرور را انجام میدهد، به صورت زیر تعریف شدهاست:
private async Task<IList<string>?> OnValidateFieldAsync(string fieldName) { switch (fieldName) { case nameof(UserDto.Name): var response = await HttpClient.PostAsJsonAsync( UserValidationUrl, new UserDto { Name = Model.Name }); var responseContent = await response.Content.ReadAsStringAsync(); if (string.Equals(responseContent, "false", StringComparison.OrdinalIgnoreCase)) { return new List<string> { $"`{Model.Name}` is in use. Please choose another name." }; } // TIP: It's better to use the `DntDebounceInputText` component for this case to reduce the network round-trips. break; } return null; }
یک نکته: InputText استاندارد در حالت معمول آن، پس از تغییر focus به یک کنترل دیگر، سبب بروز رویداد OnFieldChanged میشود و نه در حالت فشرده شدن کلیدها. به همین جهت اگر برنامه پیوستی را میخواهید آزمایش کنید، نیاز است فقط focus را تغییر دهید و یا یک کنترل سفارشی را برای اینکار توسعه دهید.
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید: BlazorAsyncValidation.zip
This project is the next generation of the ASP.NET Boilerplate web application framework.
Modular Architecture
Designed as modular and extensible from the bottom to the top.
Microservice Focused
Designed to support microservice architecture and helps to build autonomous microservices.
Domain Driven Design
Designed and developed based on DDD patterns and principles. Provides a layered model for your application.
Authorization
Advanced authorization with user, role and fine-grained permission system. Built on the Microsoft Identity library.
Multi-Tenancy
SaaS applications made easy! Integrated multi-tenancy from database to UI.
Cross Cutting Concerns
Complete infrastructure for authorization, validation, exception handling, caching, audit logging, transaction management and so on.
دورهی کامل میکروسرویسها در دات نت
.NET Microservices – Full Course, Les Jackson
In this step-by-step tutorial I take you through an introduction on building microservices using .NET. As the name suggests we build everything completely from start to finish –with the full scope of the course outlined in the time-stamp section below. However, at a high-level we’ll cover:
• Building two .NET Microservices using the REST API pattern
• Working with dedicated persistence layers for both services
• Deploying our services to Kubernetes cluster
• Employing the API Gateway pattern to route to our services
• Building Synchronous messaging between services (HTTP & gRPC)
• Building Asynchronous messaging between services using an Event Bus (RabbitMQ)