اشتراک‌ها
مروری بر SQL سورس کنترل

Why could there not be another tool that allowed a development team to harness their existing source control systems, but make database changes a part of the workflow? Enter SQL Source Control by Redgate. 

مروری بر SQL سورس کنترل
مطالب
پیاده سازی Remote Validation در Blazor
فرم‌های Blazor به همراه پشتیبانی از ویژگی Remote که به همراه ASP.NET Core ارائه می‌شود، نیستند. هرچند می‌توان در حین ارسال فرم به سرور، نتیجه‌ی اعتبارسنجی از راه دور و سمت سرور را به کاربر نمایش داد، اما تجربه‌ی کاربری آن در حد Remote validation نیست. یعنی می‌خواهیم در حین ورود اطلاعات و یا انتقال focus به کنترل دیگری، اعتبارسنجی سمت سرور صورت گیرد و نه فقط در زمان ارسال کل اطلاعات به سرور، در پایان کار. در این مطلب روشی را جهت پیاده سازی این عملیات بررسی خواهیم کرد.


ایجاد یک پروژه‌ی ابتدایی 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 زیر را برای آن تدارک خواهیم دید.


کنترلر 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>
 تنها رخ‌دادی که در اختیار ما قرار می‌گیرد، رخ‌داد submit (در حالت موفقیت اعتبارسنجی سمت کلاینت و یا تنها submit معمولی) است. بنابراین برای دسترسی به رخ‌دادهای بیشتر EditForm، نیاز است با EditContext آن کار کنیم:
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();
به همین جهت EditContext را در سطح کامپوننت جاری تعریف کرده و همچنین سرویس HttpClient را جهت ارسال اطلاعات Name و دریافت پاسخ true/false از سرور و یک ValidationMessageStore را برای نگهداری تعاریف خطاهای سفارشی که قرار است در فرم نمایش داده شوند، معرفی می‌کنیم.
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();
    }
در اینجا ابتدا یک نمونه‌ی جدید از EditContext، بر اساس Model فرم، تشکیل می‌شود. سپس ValidationMessageStore سفارشی که قرار است خطاهای اعتبارسنجی remote ما را نمایش دهد نیز نمونه سازی می‌شود. در ادامه امکان دسترسی به رخ‌دادهای OnFieldChanged ، OnValidationStateChanged و OnValidationRequested را خواهیم داشت که در حالت معمولی کار با EditForm میسر نیستند.
برای مثال اگر فیلدی تغییر کند، رویداد 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;
    }
در اینجا درخواستی به سمت آدرس api/Register/IsUserNameUnique ارسال شده و سپس بر اساس مقدار true و یا false آن، پیامی را بازگشت می‌دهد. اگر نال را بازگشت دهد یعنی مشکلی نبوده.

یک نکته: InputText استاندارد در حالت معمول آن، پس از تغییر focus به یک کنترل دیگر، سبب بروز رویداد OnFieldChanged می‌شود و نه در حالت فشرده شدن کلیدها. به همین جهت اگر برنامه پیوستی را می‌خواهید آزمایش کنید، نیاز است فقط focus را تغییر دهید و یا یک کنترل سفارشی را برای اینکار توسعه دهید.


کدهای کامل این مطلب را از اینجا می‌توانید دریافت کنید: BlazorAsyncValidation.zip
اشتراک‌ها
Modules یا Microservices؟

You Want Modules, Not Microservices
Dissecting why everybody keeps talking about microservices.
 

Modules یا Microservices؟
اشتراک‌ها
تازه‌های ASP.NET Core 3 Preview 6

ASP.NET Core 3 seems to be taking a similar tact to version 1 as it is adding a lot of functionality and phasing it in with different previews. 

تازه‌های ASP.NET Core 3 Preview 6
اشتراک‌ها
مدل Actor با استفاده از Akka.net

In the same time when first object-oriented languages were emerging, another concept inspired by general relativity and quantum mechanics was taking shape – actor model. In general terms, the Actor model was defined 1973. and was developed on a platform of multiple independent processors in a network. Similar to the object-oriented approach, this essentially mathematical model, revolved around the concept of actors. An actor is the smallest structural unit of Actor model, and just like objects, they encapsulate data and behavior. In difference to objects, however, actors communicate with each other exclusively trough messages. Messages in actors are processed in a serial manner. According to the full definition of actors, they can do three things:

  • send a finite number of messages to other actors
  • create a finite number of new actors
  • designate the behavior to be used for the next message it receives 
مدل Actor با استفاده از Akka.net