اشتراک‌ها
Angular 8 منتشر شد

Version 8 of Angular — Smaller bundles, CLI APIs, and alignment with the ecosystem 

Angular 8 منتشر شد
مطالب
بررسی تغییرات Blazor 8x - قسمت ششم - نکات تکمیلی ویژگی راهبری بهبود یافته‌ی صفحات SSR


در قسمت قبل، در حین بررسی رفتار جزیره‌های تعاملی Blazor Server، نکته‌ی زیر را هم درباره‌ی راهبری صفحات SSR مرور کردیم:
« اگر دقت کنید، جابجایی بین صفحات، با استفاده از fetch انجام شده؛ یعنی با اینکه این صفحات در اصل static HTML خالص هستند، اما ... کار full reload صفحه مانند ASP.NET Web forms قدیمی انجام نمی‌شود (و یا حتی برنامه‌های MVC و Razor pages) و نمایش صفحات، Ajax ای است و با fetch استاندارد آن صورت می‌گیرد تا هنوز هم حس و حال SPA بودن برنامه حفظ شود. همچنین اطلاعات DOM کل صفحه را هم به‌روز رسانی نمی‌کند؛ فقط موارد تغییر یافته در اینجا به روز رسانی خواهند شد.»
در این قسمت، نکات تکمیلی این قابلیت را که به آن enhanced navigation هم گفته می‌شود، بررسی می‌کنیم.


روش غیرفعال کردن راهبری بهبودیافته برای بعضی از لینک‌ها

ویژگی راهبری بهبودیافته فقط در حین هدایت بین صفحات مختلف یک برنامه‌ی Blazor 8x SSR، فعال است. اگر در این بین، کاربری به یک صفحه‌ی غیر بلیزری هدایت شود، راهبری بهبود یافته شکست خورده و سعی می‌کند حالت full document load را پیاده سازی و اجرا کند. مشکل اینجاست که در این حالت دو درخواست ارسال می‌شود: ابتدا حالت راهبری بهبودیافته فعال می‌شود و در ادامه پس از شکست این راهبری، هدایت مستقیم صورت می‌گیرد. برای رفع این مشکل می‌توان ویژگی جدید data-enhance-nav را با مقدار false، به لینک‌های خارجی مدنظر اضافه کرد تا برای این حالت‌ها دیگر ویژگی راهبری بهبودیافته فعال نشود:
<a href="/not-blazor" data-enhance-nav="false">A non-Blazor page</a>


فعالسازی مدیریت بهبودیافته‌ی فرم‌های SSR

در قسمت چهارم این سری با فرم‌های جدید SSR مخصوص Blazor 8x آشنا شدیم. این فرم‌ها هم می‌توانند از امکانات راهبری بهبود یافته استفاده کنند (یعنی مدیریت ارسال آن، توسط fetch API انجام شده و به روز رسانی قسمت‌های تغییریافته‌ی صفحه را Ajax ای انجام دهند)؛ برای نمونه اینبار همانند تصویر زیر، از fetch استاندارد برای ارسال اطلاعات به سمت سرور کمک گرفته می‌شود (یعنی عملیات Ajax ای شده‌؛ بجای یک post-back معمولی):


 اما ... این قابلیت به صورت پیش‌فرض در فرم‌های تعاملی SSR غیرفعال است. چون همانطور که عنوان شد، اگر مقصد این فرم، یک آدرس غیربلیزری باشد، دوبار ارسال فرم صورت خواهد گرفت؛ یکبار با استفاده از fetch API و بار دیگر پس از شکست، به صورت معمولی. اما اگر مطمئن هستید که endpoint این فرم، قطعا یک کامپوننت بلیزری است، بهتر است این قابلیت را در یک چنین فرم‌هایی نیز به صورت زیر فعال کنید:
<form method="post" @onsubmit="() => submitted = true" @formname="name" data-enhance>
    <AntiforgeryToken />
    <InputText @bind-Value="Name" />
    <button>Submit</button>
</form>

@if (submitted)
{
    <p>Hello @Name!</p>
}

@code {

    bool submitted;

    [SupplyParameterFromForm]
    public string Name { get; set; } = "";
}
البته باتوجه به اینکه در اینجا هم می‌توان از EditForm‌ها استفاده کرد، در این حالت فقط کافی است ویژگی Enhance را به آن‌ها اضافه نمائید:
<EditForm method="post" Model="NewCustomer" OnValidSubmit="() => submitted = true" FormName="customer" Enhance>
    <DataAnnotationsValidator />
    <ValidationSummary/>
    <p>
        <label>
            Name: <InputText @bind-Value="NewCustomer.Name" />
        </label>
    </p>
    <button>Submit</button>
</EditForm>

@if (submitted)
{
    <p id="pass">Hello @NewCustomer.Name!</p>
}

@code {
    bool submitted = false;

    [SupplyParameterFromForm]
    public Customer? NewCustomer { get; set; }

    protected override void OnInitialized()
    {
        NewCustomer ??= new();
    }

     public class Customer
    {
        [StringLength(3, ErrorMessage = "Name is too long")]
        public string? Name { get; set; }
    }
}

نکته‌ی مهم: در این حالت فرض بر این است که هیچگونه هدایتی به یک Non-Blazor endpoint صورت نمی‌گیرید؛ وگرنه با یک خطا مواجه خواهید شد.



غیرفعال کردن راهبری بهبودیافته برای قسمتی از صفحه

اگر با استفاده از جاواسکریپت و خارج از کدهای بیلزر، اطلاعات DOM را به‌روز رسانی می‌کنید، ویژگی راهبری بهبودیافته، از آن آگاهی نداشته و به صورت خودکار تمام تغییرات شما را بازنویسی می‌کند. به همین جهت اگر نیاز است قسمتی از صفحه را که مستقیما توسط کدهای جاواسکریپتی تغییر می‌دهید، از به‌روز رسانی‌های این قابلیت مصون نگه‌دارید، می‌توانید ویژگی جدید data-permanent را به آن قسمت اضافه کنید:
<div data-permanent>
    Leave me alone! I've been modified dynamically.
</div>


امکان آگاه شدن از بروز راهبری بهبودیافته در کدهای جاواسکریپتی

اگر به هردلیلی در کدهای جاواسکریپتی خودنیاز به آگاه شدن از وقوع یک هدایت بهبودیافته را دارید (برای مثال جهت بازنویسی تغییرات ایجاد شده‌ی توسط آن)، می‌توانید به نحو زیر، مشترک رخ‌دادهای آن شوید:
<script>
    Blazor.addEventListener('enhancedload', () => {
        console.log('enhanced load event occurred');
    });
</script>


ویژگی جدید Named Element Routing در Blazor 8x

Blazor 8x از ویژگی مسیریابی سمت کلاینت به کمک تعریف URL fragments پشتیبانی می‌کند. به این صورت رسیدن (اسکرول) به یک قسمت از صفحه‌ای طولانی، بسیار ساده می‌شود.
برای مثال المان h2 با id مساوی targetElement را درنظر بگیرید:
<div class="border border-info rounded bg-info" style="height:500px"></div>

<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>
در Blazor 8x برای رسیدن به آن، هر سه حالت زیر میسر هستند:
<a href="/counter#targetElement">

<NavLink href="/counter#targetElement">

Navigation.NavigateTo("/counter#targetElement");


معرفی متد جدید Refresh در Blazor 8x

در Blazor 8x، امکان بارگذاری مجدد صفحه با فراخوانی متد جدید NavigationManager.Refresh(bool forceLoad = false) میسر شده‌است. این متد در حالت پیش‌فرض از قابلیت راهبری بهبودیافته برای به روز رسانی صفحه استفاده می‌کند؛ مگر اینکه اینکار میسر نباشد. اگر آن‌را با پارامتر true فراخوانی کنید، full-page reload رخ خواهد داد.
همین اتفاق در مورد متد Navigation.NavigateTo نیز رخ‌داده‌است. این متد نیز در Blazor 8x به صورت پیش‌فرض بر اساس قابلیت راهبری بهبود یافته کار می‌کند؛ مگر اینکه اینکار میسر نباشد و یا پارامتر forceLoad آن‌را به true مقدار دهی کنید.
مطالب
C# 12.0 - Using aliases for any type
دات‌نت 8 به همراه بهبودهای قابل ملاحظه‌ای در کارآیی برنامه‌های دات‌نتی است و در این بین تعدادی قابلیت جدید را نیز به زبان سی‌شارپ اضافه کرده‌است. در این مطلب ویژگی جدید «Alias any type» آن‌را بررسی می‌کنیم. پیشنیاز کار با این قابلیت تنها نصب SDK دات‌نت 8 است.


امکان تعریف alias، قابلیت جدیدی نیست!

در نگارش‌های پیشین زبان #C نیز می‌توان برای نوع‌های نام‌دار دات‌نت، alias/«نام مستعار» تعریف کرد؛ برای مثال:
using MyConsole = System.Console;

MyConsole.WriteLine("Test console");
Aliasها در قسمت using تعاریف یک کلاس معرفی می‌شوند و یکی از اهدف آن‌ها، کوتاه کردن تعاریف فضاهای نام طولانی است و یا رفع تداخل‌ها؛ همچنین تنها به Named types، محدود هستند و Named types فقط شامل این موارد می‌شوند: classes ،delegates ،interfaces ،records و structs

بنابراین دو حالت تعریف Namespace alias برای کوتاه سازی فضاهای نام طولانی و یا تعریف Type alias برای معرفی یک نام مستعار جدید برای نوعی مشخص، میسر است:
// Namespace alias
using SuperJSON = System.Text.Json;
var document = SuperJSON.JsonSerializer.Serialize("{}");

// Type alias
using SuperJSON = System.Text.Json.JsonSerializer;
var document = SuperJSON.Serialize("{}");

تنها کارکرد نام‌های مستعار، کوتاه و زیبا سازی نام‌های طولانی نیستند. برای مثال گاهی از اوقات ممکن است که بین نام نوع‌های موجود در usingهای جاری، تداخل حاصل شود و برنامه کامپایل نشود. برای مثال فرض کنید که دو using زیر را تعریف کرده‌اید:
using UnityEngine;
using System;

Random rnd = new Random();
کامپایل این برنامه میسر نیست. چون هر دو نوع System.Random و UnityEngine.Random پیشتر تعریف شده‌اند و در اینجا دقیقا مشخص نیست که تامین کننده‌ی شیء Random، کدام فضای نام است. در این حالت می‌توان برای مثال در حین نمونه سازی، فضای نام را صراحتا ذکر کرد:
var rnd = new System.Random();
و یا می‌توان برای آن نام مستعاری نیز تعریف کرد:
using Random = System.Random;
در این حالت دیگر تداخلی وجود نداشته و کامپایلر دقیقا می‌داند که تامین کننده‌ی Random، کدام کتابخانه و کدام فضای نام است.


امکان تعریف alias برای هر نوعی در C# 12.0

محدودیت امکان تعریف alias برای نوع‌های نام‌دار دات‌نت در C# 12.0 برطرف شده و اکنون می‌توان برای انواع و اقسام نوع‌ها مانند آرایه‌ها، tuples و غیره نیز alias تعریف کرد:
using Ints = int[];
using DatabaseInt = int?;
using OptionalFloat = float?;
using Grade= decimal;
using Point3D = (int, int, int);
using Person = (string name, int age, string country);
using unsafe P = char*;
using Matrix = int[][];

Matrix aMatrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
در اینجا امکان تعریف alias را برای آرایه‌ها، nullable value types، نوع‌های توکار، tupleها و حتی نوع‌های unsafe، مشاهده می‌کنید.
یک نکته: امکان تعریف alias برای nullable reverence types وجود ندارد.


بررسی یک مثال C# 12.0

در اینجا محتویات یک فایل Program.cs یک برنامه‌ی کنسول دات‌نت 8 را مشاهده می‌کنید:
using MyConsole = System.Console;
using Person = (string name, int age, string country);

Person person = new("User 1", 33, "Iran");
Console.WriteLine(person);
PrintPerson(person);

MyConsole.WriteLine("Test console");

static void PrintPerson(Person person)
{
   MyConsole.WriteLine($"{person.name}, {person.age}, {person.country}");
}
در این مثال برای یک نوع tuple سفارشی، یک alias به نام Person تعریف شده و سپس از آن برای نمونه سازی یک شیء جدید و یا ارسال آن به عنوان یک پارامتر متد، استفاده شده‌است. خروجی برنامه‌ی فوق به صورت زیر است:
(User 1, 33, Iran)
User 1, 33, Iran
Test console


چه زمانی بهتر است از قابلیت تعریف نام‌های مستعار نوع‌ها و یا فضاهای نام استفاده شود؟

اگر یک نام طولانی را بتوان به این صورت خلاصه کرد، مفید هستند؛ برای مثال ساده سازی تعریف یک لیست طولانی به صورت زیر:
using Companies = System.Collections.Generic.List<Company>;

Companies GetCompanies()
{
   // logic here
}

class Company
{
   public string Name;
   public int Id;
}
و مثالی دیگر در این زمینه، کوتاه سازی تعاریف متداول جنریک طولانی است:
using EventHandlers = System.Collections.Generic.IEnumerable<System.Func<System.Threading.Tasks.Task>>;

 و یا اگر بتوانند رفع تداخلی را حاصل کنند، بکارگیری آن‌ها ضروری است (مانند مثال شیء Random ابتدای بحث) و یا اگر بتوانند از تکرار تعریف یک tuple جلوگیری کنند، ذکر آن‌ها یک refactoring مثبت به‌شمار می‌رود؛ مانند مثال زیر که در آن از تعریف نوع tuple ای، دوبار استفاده شده‌است:
using Country = (string Abbreviation, string Name);

Country GetCountry(string abbreviation)
{
   // Logic here
}

List<Country> GetCountries()
{
   // Logic here
}
 اما ... آیا واقعا تعاریفی مانند ذیل، مفید یا ضروری هستند؟
using Ints = int[];
using DatabaseInt = int?;
using OptionalFloat = float?;
اینجا فقط قطعه کدی اضافی را که بیشتر سبب سردرگمی و بالا بردن درجه‌ی پیچیدگی برنامه می‌شود، تولید کرده‌ایم. خوانایی و سادگی درک برنامه در این حالت کاهش پیدا می‌کند.


میدان دید نام‌های مستعار

به صورت پیش‌فرض، تمام نام‌های مستعار تنها در داخل همان فایلی که تعریف شده‌اند، قابل استفاده می‌باشند. از زمان C# 10.0 ، می‌توان پیش از واژه‌ی کلیدی using از واژه‌ی کلیدی global نیز استفاده کرد تا تعریف آن‌ها فقط در پروژه‌ی جاری به صورت سراسری قابل دسترسی شود.
به همین جهت اگر نوعی قرار است در سایر پروژه‌ها استفاده شود، بهتر است از global using استفاده نشده و از همان روش‌های متداول تعریف records و یا classes استفاده شود.
مطالب
بررسی تغییرات Blazor 8x - قسمت یازدهم - قالب جدید پیاده سازی اعتبارسنجی و احراز هویت - بخش اول
قالب‌های پیش‌فرض Blazor 8x، به همراه قسمت بازنویسی شده‌ی ASP.NET Core Identity برای Blazor هم هستند که در این قسمت به بررسی نحوه‌ی عملکرد آن‌ها می‌پردازیم.


معرفی قالب‌های جدید شروع پروژه‌های Blazor در دات نت 8 به همراه قسمت Identity

در قسمت دوم این سری، با قالب‌های جدید شروع پروژه‌های Blazor 8x آشنا شدیم و هدف ما در آنجا بیشتر بررسی حالت‌های مختلف رندر Blazor در دات نت 8 بود. تمام این قالب‌ها به همراه یک سوئیچ دیگر هم به نام auth-- هستند که توسط آن و با مقدار دهی Individual که به معنای Individual accounts است، می‌توان کدهای پیش‌فرض و ابتدایی Identity UI جدید را نیز به قالب در حال ایجاد، به صورت خودکار اضافه کرد؛ یعنی به صورت زیر:

اجرای قسمت‌های تعاملی برنامه بر روی سرور؛ به همراه کدهای Identity:
dotnet new blazor --interactivity Server --auth Individual

اجرای قسمت‌های تعاملی برنامه در مرورگر، توسط فناوری وب‌اسمبلی؛ به همراه کدهای Identity:
dotnet new blazor --interactivity WebAssembly --auth Individual

برای اجرای قسمت‌های تعاملی برنامه، ابتدا حالت Server فعالسازی می‌شود تا فایل‌های WebAssembly دریافت شوند، سپس فقط از WebAssembly استفاده می‌کند؛ به همراه کدهای Identity:
dotnet new blazor --interactivity Auto --auth Individual

فقط از حالت SSR یا همان static server rendering استفاده می‌شود (این نوع برنامه‌ها تعاملی نیستند)؛ به همراه کدهای Identity:
dotnet new blazor --interactivity None --auth Individual

 و یا توسط پرچم all-interactive--، که interactive render mode را در ریشه‌ی برنامه قرار می‌دهد؛ به همراه کدهای Identity:
 dotnet new blazor --all-interactive --auth Individual

یک نکته: بانک اطلاعاتی پیش‌فرض مورد استفاده‌ی در این نوع پروژه‌ها، SQLite است. برای تغییر آن می‌توانید از پرچم use-local-db-- هم استفاده کنید تا از LocalDB بجای SQLite استفاده کند.


Identity UI جدید Blazor در دات نت 8، یک بازنویسی کامل است


در نگارش‌های قبلی Blazor هم امکان افزودن Identity UI، به پروژه‌های Blazor وجود داشت (اطلاعات بیشتر)، اما ... آن پیاده سازی، کاملا مبتنی بر Razor pages بود. یعنی کاربر، برای کار با آن مجبور بود از فضای برای مثال Blazor Server خارج شده و وارد فضای جدید ASP.NET Core شود تا بتواند، Identity UI نوشته شده‌ی با صفحات cshtml. را اجرا کند و به اجزای آن دسترسی پیدا کند (یعنی عملا آن قسمت UI اعتبارسنجی، Blazor ای نبود) و پس از اینکار، مجددا به سمت برنامه‌ی Blazor هدایت شود؛ اما ... این مشکل در دات نت 8 با ارائه‌ی صفحات SSR برطرف شده‌است.
همانطور که در قسمت قبل نیز بررسی کردیم، صفحات SSR، طول عمر کوتاهی دارند و هدف آن‌ها تنها ارسال یک HTML استاتیک به مرورگر کاربر است؛ اما ... دسترسی کاملی را به HttpContext برنامه‌ی سمت سرور دارند و این دقیقا چیزی است که زیر ساخت Identity، برای کار و تامین کوکی‌های مورد نیاز خودش، احتیاج دارد. صفحات Identity UI از یک طرف از HttpContext برای نوشتن کوکی لاگین موفقیت آمیز در مرورگر کاربر استفاده می‌کنند (در این سیستم، هرجائی متدهای XyzSignInAsync وجود دارد، در پشت صحنه و در پایان کار، سبب درج یک کوکی اعتبارسنجی و احراز هویت در مرورگر کاربر نیز خواهد شد) و از طرف دیگر با استفاده از میان‌افزارهای اعتبارسنجی و احراز هویت ASP.NET Core، این کوکی‌ها را به صورت خودکار پردازش کرده و از آن‌ها جهت ساخت خودکار شیء User قابل دسترسی در این صفحات (شیء context.User.Identity@)، استفاده می‌کنند.
به همین جهت تمام صفحات Identity UI ارائه شده در Blazor 8x، از نوع SSR هستند و اگر در آن‌ها از فرمی استفاده شده، دقیقا همان فرم‌های تعاملی است که در قسمت چهارم این سری بررسی کردیم. یعنی صرفا بخاطر داشتن یک فرم، ضرورتی به استفاده‌ی از جزایر تعاملی Blazor Server و یا Blazor WASM را ندیده‌اند و اینگونه فرم‌ها را بر اساس مدل جدید فرم‌های تعاملی Blazor 8x پیاده سازی کرده‌اند. بنابراین این صفحات کاملا یکدست هستند و از ابتدا تا انتها، به صورت یکپارچه بر اساس مدل SSR کار می‌کنند (که در اصل خیلی شبیه به Razor pages یا Viewهای MVC هستند) و جزیره، جزیره‌ای، طراحی نشده‌اند.

 
روش دسترسی به HttpContext در صفحات SSR

اگر به کدهای Identity UI قالب آغازین یک پروژه که در ابتدای بحث روش تولید آن‌ها بیان شد، مراجعه کنید، استفاده از یک چنین «پارامترهای آبشاری» را می‌توان مشاهده کرد:

@code {

    [CascadingParameter]
    public HttpContext HttpContext { get; set; } = default!;
متد ()AddRazorComponents ای که در فایل Program.cs اضافه می‌شود، کار ثبت CascadingParameter ویژه‌ی فوق را به صورت زیر انجام می‌دهد که در Blazor 8x به آن یک Root-level cascading value می‌گویند:
services.TryAddCascadingValue(sp => sp.GetRequiredService<EndpointHtmlRenderer>().HttpContext);
مقادیر آبشاری برای ارسال اطلاعاتی بین درختی از کامپوننت‌ها، از یک والد به چندین فرزند که چندین لایه ذیل آن واقع شده‌‌اند، مفید است. برای مثال فرض کنید می‌خواهید اطلاعات عمومی تنظیمات یک کاربر را به چندین زیر کامپوننت، ارسال کنید. یک روش آن، ارسال شیء آن به صورت پارامتر، به تک تک آن‌ها است و راه دیگر، تعریف یک CascadingParameter است؛ شبیه به کاری که در اینجا انجام شده‌است تا دیگر نیازی نباشد تا تک تک زیر کامپوننت‌ها این شیء را به یک لایه زیریرین خود، یکی یکی منتقل کنند.

در کدهای Identity UI ارائه شده، از این CascadingParameter برای مثال جهت خروج از برنامه (HttpContext.SignOutAsync) و یا دسترسی به اطلاعات هدرهای رسید (if (HttpMethods.IsGet(HttpContext.Request.Method)))، دسترسی به سرویس‌ها (()<HttpContext.Features.Get<ITrackingConsentFeature)، تامین مقدار Cancellation Token به کمک HttpContext.RequestAborted و یا حتی در صفحه‌ی جدید Error.razor که آن نیز یک صفحه‌ی SSR است، برای دریافت HttpContext?.TraceIdentifier استفاده‌ی مستقیم شده‌است.

نکته‌ی مهم: باید به‌خاطر داشت که فقط و فقط در صفحات SSR است که می‌توان به HttpContext به نحو آبشاری فوق دسترسی یافت و همانطور که در قسمت قبل نیز بررسی شد، سایر حالات رندر Blazor از دسترسی به آن، پشتیبانی نمی‌کنند و اگر چنین پارامتری را تنظیم کردید، نال دریافت می‌کنید.


بررسی تفاوت‌های تنظیمات ابتدایی قالب جدید Identity UI در Blazor 8x با نگارش‌های قبلی آن

مطالب و نکات مرتبط با قالب قبلی را در مطلب «Blazor 5x - قسمت 22 - احراز هویت و اعتبارسنجی کاربران Blazor Server - بخش 2 - ورود به سیستم و خروج از آن» می‌توانید مشاهده کنید.

در قسمت سوم این سری، روش ارتقاء یک برنامه‌ی قدیمی Blazor Server را به نگارش 8x آن بررسی کردیم و یکی از تغییرات مهم آن، حذف فایل‌های cshtml. ای آغاز برنامه و انتقال وظایف آن، به فایل جدید App.razor و انتقال مسیریاب Blazor به فایل جدید Routes.razor است که پیشتر در فایل App.razor نگارش‌های قبلی Blazor وجود داشت.
در این نگارش جدید، محتوای فایل Routes.razor به همراه قالب Identity UI به صورت زیر است:
<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
</Router>
در نگارش‌های قبلی، این مسیریاب داخل کامپوننت CascadingAuthenticationState محصور می‌شد تا توسط آن بتوان AuthenticationState را به تمام کامپوننت‌های برنامه ارسال کرد. به این ترتیب برای مثال کامپوننت AuthorizeView، شروع به کار می‌کند و یا توسط شیء context.User می‌توان به User claims دسترسی یافت و یا به کمک ویژگی [Authorize]، دسترسی به صفحه‌ای را محدود به کاربران اعتبارسنجی شده کرد.
اما ... در اینجا با یک نگارش ساده شده سروکار داریم؛ از این جهت که برنامه‌های جدید، به همراه جزایر تعاملی هم می‌توانند باشند و باید بتوان این AuthenticationState را به آن‌ها هم ارسال کرد. به همین جهت مفهوم جدید مقادیر آبشاری سطح ریشه (Root-level cascading values) که پیشتر در این بحث معرفی شد، در اینجا برای معرفی AuthenticationState استفاده شده‌است.

در اینجا کامپوننت جدید FocusOnNavigate را هم مشاهده می‌کنید. با استفاده از این کامپوننت و براساس CSS Selector معرفی شده، پس از هدایت به یک صفحه‌ی جدید، این المان مشخص شده دارای focus خواهد شد. هدف از آن، اطلاع رسانی به screen readerها در مورد هدایت به صفحه‌ای دیگر است (برای مثال، کمک به نابیناها برای درک بهتر وضعیت جاری).

همچنین در اینجا المان NotFound را هم مشاهده نمی‌کنید. این المان فقط در برنامه‌های WASM جهت سازگاری با نگارش‌های قبلی، هنوز هم قابل استفاده‌است. جایگزین آن‌را در قسمت سوم این سری، برای برنامه‌های Blazor server در بخش «ایجاد فایل جدید Routes.razor و مدیریت سراسری خطاها و صفحات یافت نشده» آن بررسی کردیم.


روش انتقال اطلاعات سراسری اعتبارسنجی یک کاربر به کامپوننت‌ها و جزایر تعاملی واقع در صفحات SSR

مشکل! زمانیکه از ترکیب صفحات SSR و جزایر تعاملی واقع در آن استفاده می‌کنیم ... جزایر واقع در آن‌ها دیگر این مقادیر آبشاری را دریافت نمی‌کنند و این مقادیر در آن‌ها نال است. برای حل این مشکل در Blazor 8x، باید مقادیر آبشاری سطح ریشه را (Root-level cascading values) به صورت زیر در فایل Program.cs برنامه ثبت کرد:
builder.Services.AddCascadingValue(sp =>new Preferences { Theme ="Dark" });
پس از این تغییر، اکنون نه فقط صفحات SSR، بلکه جزایر واقع در آن‌ها نیز توسط ویژگی [CascadingParameter] می‌توانند به این مقدار آبشاری، دسترسی داشته باشند. به این ترتیب است که در برنامه‌های Blazor، کامپوننت‌های تعاملی هم دسترسی به اطلاعات شخص لاگین شده‌ی توسط صفحات SSR را دارند. برای مثال اگر به فایل Program.cs قالب جدید Identity UI عنوان شده مراجعه کنید، چنین سطوری در آن قابل مشاهده هستند
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();
متد جدید AddCascadingAuthenticationState، فقط کار ثبت AuthenticationStateProvider برنامه را به صورت آبشاری انجام می‌دهد.
این AuthenticationStateProvider سفارشی جدید هم در فایل اختصاصی IdentityRevalidatingAuthenticationStateProvider.cs پوشه‌ی Identity قالب پروژه‌های جدید Blazor 8x که به همراه اعتبارسنجی هستند، قابل مشاهده‌است.

یا اگر به قالب‌های پروژه‌های WASM دار مراجعه کنید، تعریف به این صورت تغییر کرده‌است؛ اما مفهوم آن یکی است:
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<AuthenticationStateProvider, PersistingServerAuthenticationStateProvider>();
در این پروژه‌ها، یک AuthenticationStateProvider سفارشی دیگری در فایل PersistingServerAuthenticationStateProvider.cs ارائه شده‌است (این فایل‌ها، جزو استاندارد قالب‌های جدید Identity UI پروژه‌های Blazor 8x هستند؛ فقط کافی است، یک نمونه پروژه‌ی آزمایشی را با سوئیچ جدید auth Individual-- ایجاد کنید، تا بتوانید این فایل‌های یاد شده را مشاهده نمائید).

AuthenticationStateProviderهای سفارشی مانند کلاس‌های IdentityRevalidatingAuthenticationStateProvider و PersistingServerAuthenticationStateProvider که در این قالب‌ها موجود هستند، چون به صورت آبشاری کار تامین AuthenticationState را انجام می‌دهند، به این ترتیب می‌توان به شیء context.User.Identity@ در جزایر تعاملی نیز به سادگی دسترسی داشت.

یعنی به صورت خلاصه، یکبار قرارداد AuthenticationStateProvider عمومی (بدون هیچ نوع پیاده سازی) به صورت یک Root-level cascading value ثبت می‌شود تا در کل برنامه قابل دسترسی شود. سپس یک پیاده سازی اختصاصی از آن توسط ()<builder.Services.AddScoped<AuthenticationStateProvider, XyzProvider به برنامه معرفی می‌شود تا آن‌را تامین کند. به این ترتیب زیر ساخت امن سازی صفحات با استفاده از ویژگی attribute [Authorize]@ و یا دسترسی به اطلاعات کاربر جاری با استفاده از شیء context.User@ و یا امکان استفاده از کامپوننت AuthorizeView برای نمایش اطلاعاتی ویژه به کاربران اعتبارسنجی شده مانند صفحه‌ی Auth.razor زیر، مهیا می‌شود:
@page "/auth"

@using Microsoft.AspNetCore.Authorization

@attribute [Authorize]

<PageTitle>Auth</PageTitle>

<h1>You are authenticated</h1>

<AuthorizeView>
    Hello @context.User.Identity?.Name!
</AuthorizeView>

سؤال: چگونه یک پروژه‌ی سمت سرور، اطلاعات اعتبارسنجی خودش را با یک پروژه‌ی WASM سمت کلاینت به اشتراک می‌گذارد (برای مثال در حالت رندر Auto)؟ این انتقال اطلاعات باتوجه به یکسان نبودن محل اجرای این دو پروژه (یکی بر روی کامپیوتر سرور و دیگری بر روی مرورگر کلاینت، در کامپیوتری دیگر) چگونه انجام می‌شود؟ این مورد را در قسمت بعد، با معرفی PersistentComponentState و «فیلدهای مخفی» مرتبط با آن، بررسی می‌کنیم.
اشتراک‌ها
آنگولار متریال 1 منتشر شد

What makes 1.0 different from our pre-release builds?

  • Stable CSS and API surface.We're now confident in the API for these components and do not plan any breaking changes.
  • Supported platforms: Tested on IE 11+, Chrome, Safari, Firefox, Android 4.2+ and iOS 8+.
  • Angular 1.5-ready. You can use AngularJS 1.3 and later, but as soon as you update to the new release, you can be confident that ngMaterial components will continue to work as expected. 
آنگولار متریال 1 منتشر شد
اشتراک‌ها
نگران Angular 3 نباشید

in Angular 1.x we had this:

  • Angular 1.0 - major version
  • Angular 1.1 - major version (well, more a preview of Angular 1.2)
  • Angular 1.2 - major version
  • Angular 1.3 - major version (dropped IE8 support)
  • Angular 1.4 - major version
  • Angular 1.5 - major version

In “Angular 2”, you’re looking at this:

  • Angular 2 - major version
  • Angular 3 - major version
  • Angular 4 - major version
  • Angular 5 - major version
  • Angular 6 - major version
  • Angular 7 - major version 
نگران Angular 3 نباشید