نظرات مطالب
مستند سازی ASP.NET Core 2x API توسط OpenAPI Swagger - قسمت ششم - تکمیل مستندات محافظت از API
این روش برای نوشتن دلیل شکست عملیات در response body، با بازنویسی متد HandleChallengeAsync، آزمایش شده:
using System.Security.Claims;
using System.Text;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Options;

namespace OpenAPISwaggerDoc.Web.Authentication;

public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
    private string _failReason;

    public BasicAuthenticationHandler(
        IOptionsMonitor<AuthenticationSchemeOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder,
        ISystemClock clock)
        : base(options, logger, encoder, clock)
    {
    }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        if (!Request.Headers.ContainsKey("Authorization"))
        {
            _failReason = "Missing Authorization header";
            return Task.FromResult(AuthenticateResult.Fail(_failReason));
        }

        try
        {
            var authenticationHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
            var credentialBytes = Convert.FromBase64String(authenticationHeader.Parameter);
            var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':');
            var username = credentials[0];
            var password = credentials[1];

            if (string.Equals(username, "DNT", StringComparison.Ordinal) &&
                string.Equals(password, "123", StringComparison.Ordinal))
            {
                var claims = new[] { new Claim(ClaimTypes.NameIdentifier, username) };
                var identity = new ClaimsIdentity(claims, Scheme.Name);
                var principal = new ClaimsPrincipal(identity);
                var ticket = new AuthenticationTicket(principal, Scheme.Name);
                return Task.FromResult(AuthenticateResult.Success(ticket));
            }

            _failReason = "Invalid username or password";
            return Task.FromResult(AuthenticateResult.Fail(_failReason));
        }
        catch
        {
            _failReason = "Invalid Authorization header";
            return Task.FromResult(AuthenticateResult.Fail(_failReason));
        }
    }

    protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
    {
        await base.HandleChallengeAsync(properties);
        if (Response.StatusCode == StatusCodes.Status401Unauthorized &&
            !string.IsNullOrWhiteSpace(_failReason))
        {
            Response.Headers.Add("WWW-Authenticate", _failReason);
            Response.ContentType = "application/json";
            await WriteProblemDetailsAsync(_failReason);
        }
    }

    private Task WriteProblemDetailsAsync(string detail)
    {
        var problemDetails = new ProblemDetails { Detail = detail, Status = Context.Response.StatusCode };
        var result = new ObjectResult(problemDetails)
                     {
                         ContentTypes = new MediaTypeCollection(),
                         StatusCode = problemDetails.Status,
                         DeclaredType = problemDetails.GetType(),
                     };
        var executor = Context.RequestServices.GetRequiredService<IActionResultExecutor<ObjectResult>>();
        var routeData = Context.GetRouteData() ?? new RouteData();
        var actionContext = new ActionContext(Context, routeData, new ActionDescriptor());
        return executor.ExecuteAsync(actionContext, result);
    }
}
بازخوردهای دوره
مدیریت نگاشت ConnectionIdها در SignalR به کاربران واقعی سیستم
استفاده از متغیرهای استاتیک و حافظه‌ی سرور برای کش کردن (مانند مثال جاری)، مقیاس پذیر نیست. در این موارد روش توصیه شده، استفاده از بانک اطلاعاتی Key/Value فوق سریع Redis هست که اتفاقا با SignalR هم زیاد استفاده می‌شود.
دوره‌ها
RavenDB
RavenDB یک بانک اطلاعاتی سورس باز NoSQL سندگرای تهیه شده با دات نت است. در این دوره به بررسی جزئیات نحوه کار با آن خواهیم پرداخت.
اشتراک‌ها
SQLite در Windows 10

با همکاری مایکروسافت و تیم SQLite این بانک اطلاعاتی قرار است به عنوان جزئی از اجزای سیستمی ویندوز، معرفی، پشتیبانی، به روز رسانی و نگهداری شود.

SQLite در Windows 10
نظرات مطالب
کار با چندین نوع بانک اطلاعاتی متفاوت در Entity Framework Core
با سلام.
اگر بانک اطلاعاتی MariaDB هم باشد باز روال کار به همین صورت است؟
آیا IDesignTimeDbContextFactory  فعلی که زحمت کشیدید، فقط مخصوص SQLite می‌باشد؟
با سپاس فراوان.
نظرات مطالب
کوئری نویسی در EF Core - قسمت اول - تشکیل بانک اطلاعاتی و مقدار دهی اولیه‌ی آن
بله. هدف ثبت اطلاعات ابتدایی فایل SQL همراه آن در بانک اطلاعاتی است. این IDها هم به علت رابطه‌هایی که بین جداول وجود دارند، باید به همین نحو و با همین مقدارها ثبت شوند.
نظرات مطالب
معرفی قالب پروژه Web API مبتنی‌بر ASP.NET Core Web API و زیرساخت DNTFrameworkCore
برای انتقال این منابع به یک بانک اطلاعاتی، نیاز است مهیا کننده مرتبط با آن را طراحی و پیاده‌سازی کنید. به عنوان مثال کتابخانه Localization.SqlLocalizer به عنوان یک راه‌حل می‌تواند مورد استفاده قرار گیرد.