مطالب
آشنایی با LibMan در پروژه‌های ASP.NET Core
مدیریت پکیج‌های سمت کلاینت
پروژه‌های جدیدی که با استفاده از قالب پیش‌فرض ایجاد می‌شوند، شامل یک پوشه با نام lib، در شاخه‌ی wwwroot هستند که حاوی این فایل‌ها می‌باشند:


اینها به عنوان حداقل‌های ایجاد یک وب اپلیکیشن، برای قالب انتخاب شده در نظر گرفته شده‌اند. اما فرض کنید بعد از مدتی می‌خواهیم ورژن bootstrap استفاده شده در پروژه را ارتقاء دهیم؛ در این حالت چندین انتخاب داریم:

  • دانلود مستقیم فایل موردنیاز و جایگزین کردن آن با نسخه‌ی فعلی
  • حذف پوشه‌ی wwwroot/lib و نصب مجدد پوشه‌ها از طریق NPM یا Yarn
  • استفاده از bower و سفارشی‌سازی مسیر قرار گرفتن فایل‌ها توسط browerrc.

روش اول، به نسبت ساده‌تر است؛ اما مشکل اینجاست که همه چیز به صورت دستی انجام خواهد گرفت. یعنی برای نسخه‌های بعدی همین روال باید مجدداً انجام شود. در روش دوم نیز مشکل اینجاست که مسیر قرار گرفتن پکیج‌های پروژه، از این به بعد node_modules خواهند بود و نیاز به یک تنظیم اضافی در فایل Startup.cs و مطلع کردن ASP.NET Core برای serve کردن فایل‌های سمت کلاینت است همچنین نیاز خواهد بود که تمامی ارجاعات داخل فایل Layout.cshtmlـ نیز از lib به node_modules تغییر پیدا کنند. در نهایت روش آخر نیز به دلیل منسوخ شدن bower پیشنهاد نمی‌شود.

استفاده از LibMan 
LibMan یک قابلیت جدید است که از نسخه‌ی Visual Studio 2017 برای مدیریت پکیج‌های سمت کلاینت اضافه شده است. این ابزار به صورت cross platform تهیه شده است؛ یعنی در خارج از Visual Studio نیز قابل استفاده می‌باشد. در واقع این ابزار را می‌توانیم به صورت Globally روی سیستم خود نصب کنیم و از طریق خط فرمان همانند NPM از آن استفاده کنیم.  

نصب و استفاده از LibMan
این ابزار ابتدا توسط Mads Kristensen با عنوان Client-Side Library Installer به صورت یک افزونه برای Visual Studio 2015 توسعه داده شد که در نهایت تیم ASP.NET این ابزار را  به صورت توکار به Visual Studio 2017 اضافه کرد. در نتیجه اگر از نسخه‌ی 2017 ویژوال استودیو استفاده می‌کنید، برای استفاده از این ابزار نیاز به نصب پکیج خاصی نخواهید داشت. برای استفاده از این ابزار در سیستم‌عامل‌های به غیر از ویندوز نیز یک CLI تهیه شده است که از طریق خط فرمان قابل استفاده می‌باشد. برای نصب این ابزار کافی است ابتدا آن را به صورت سراسری نصب کنید:
dotnet tool install -g Microsoft.Web.LibraryManager.Cli

قدم بعدی اضافه کردن فایلی با عنوان libman.json درون پروژه است. برای افزودن این فایل کافی است دستور زیر را در خطر فرمان وارد کنید:
libman init

با صدور فرمان فوق فایل مربوطه درون پروژه ایجاد می‌شود که در واقع یک فایل json ساده برای مدیریت پکیج‌های سمت کلاینت است:
{
  "version": "1.0",
  "defaultProvider": "cdnjs",
  "libraries": []
}

همانطور که مشاهده می‌کنید، می‌توانیم منبع دریافت پکیج‌‌ها را نیز تعیین کنیم که در حالت پیش‌فرض بر روی cdnjs تنظیم شده‌است و در واقع یک Content Delivery Network برای تعداد بیشماری پکیج سمت کلاینت است. درون آرایه‌ی libraries نیز می‌توانیم پکیج‌های موردنیاز خود را وارد کنیم. حتی برای هر پکیج هم می‌توانیم provider را override نمائیم. فرض کنید می‌خواهیم کتابخانه‌ی bootstrap را به پروژه اضافه کنیم. در اینحالت کافی است دستور زیر را برای نصب پکیج مربوطه صادر نمائیم:
libman install bootstrap@4.3.1 --provider unpkg --destination wwwroot/lib/bootstrap

در نهایت فایل libman.json چنین ساختاری پیدا خواهد کرد:
{
  "version": "1.0",
  "defaultProvider": "cdnjs",
  "libraries": [
    {
      "provider": "unpkg",
      "library": "bootstrap@4.3.1",
      "destination": "wwwroot/lib/bootstrap"
    }
  ]
}

برای نصب مجدد پکیج هم می‌توانید از دستور libman restore استفاده کنید؛ در این حالت دقیقا مانند Nuget، پکیج‌ها از روی فایل libman.json از provider مربوطه دانلود و به پروژه اضافه خواهند شد. در ادامه لیست دستورات موجود را مشاهده می‌کنید:

مطالب
ASP.NET Web API - قسمت پنجم
مدیریت کدهای وضعیت در Web API
تمامی پاسخ‌های دریافتی از Web API توسط Client، باید در قالب کدهای وضعیت HTTP باشند. دو کلاس جدید با نام‌های HttpResponseMessage و HttpResponseException همراه با ASP.NET MVC 4 معرفی شده اند که ارسال کدهای وضعیت پردازش درخواست به Client را آسان می‌سازند. به عنوان مثال، ارسال وضعیت برای چهار عمل اصلی بازیابی، ایجاد، آپدیت و حذف رکورد را بررسی می‌کنیم.

بازیابی رکورد
بر اساس مستندات پروتوکل HTTP، در صورتی که منبع درخواستی Client پیدا نشد، باید کد وضعیت 404 برگشت داده شود. این حالت را در متد ذیل پیاده سازی کرده ایم.
public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)); 
    }
    return item;
}
در صورتی که رکوردی با مشخصه‌ی درخواستی پیدا نشد، با استفاده از کلاس HttpResponseException، خطایی به Client ارسال خواهد شد. پارامتر سازنده‌ی این کلاس، شی ای از نوع کلاس HttpResponseMessage است. سازنده‌ی کلاس HttpResponseMessage، مقداری از یک enum با نام HttpStatusCode را می‌پذیرد. مقدار NotFound، نشان از خطای 404 است و زمانی به کار می‌رود که منبع درخواستی وجود نداشته باشد. اگر محصول درخواست شده یافت شد، در قالب JSON برگشت داده می‌شود. در شکل ذیل، پاسخ دریافتی در زمان درخواست محصولی که وجود ندارد را ملاحظه می‌کنید.

ایجاد رکورد
برای ایجاد رکورد، Client درخواستی از نوع POST را همراه با داده‌های رکورد در بدنه‌ی درخواست به Server ارسال می‌کند. در ذیل، پیاده سازی ساده ای از این حالت را مشاهده می‌کنید.
public Product PostProduct(Product item)
{
    item = repository.Add(item);
    return item;
}
 این پیاده سازی کار می‌کند اما کمبودهایی دارد:
  • کد وضعیت پردازش درخواست: به طور پیش فرض، Web API، کد 200 را در پاسخ ارسال می‌کند، اما بر اساس مستندات پروتوکل HTTP، زمانی که یک درخواست از نوع POST منجر به تولید منبعی می-شود، Server باید کد وضعیت 201 را به Client برگشت بدهد.
  • آدرس منبع جدید ایجاد شده: بر اساس مستندات پروتوکل HTTP، زمانی که منبعی بر روی Server ایجاد می‌شود، باید آدرس منبع جدید ایجاد شده از طریق هدر Location به Client ارسال شود.
با توجه به این توضیحات، متد قبل به صورت ذیل در خواهد آمد.
public HttpResponseMessage PostProduct(Product item)
{
    item = repository.Add(item);
    var response = Request.CreateResponse(HttpStatusCode.Created, item);

    string uri = Url.Link("DefaultApi", new { id = item.Id });
    response.Headers.Location = new Uri(uri);
    return response;
}
همان طور که ملاحظه می‌کنید، خروجی متد از نوع کلاس HttpResponseMessage است، چون با استفاده از این نوع می‌توانیم جزئیات مورد نیاز را در مورد نتیجه‌ی پردازش درخواست به مرورگر ارسال کنیم. همچنین، داده‌های رکورد جدید نیز در بدنه‌ی پاسخ، با یک فرمت مناسب مانند XML یا JSON برگشت داده می‌شوند. با استفاده از متد CreateResponse کلاس Request و پاس دادن کد وضعیت و شی ای که قصد داریم به Client ارسال شود به این متد، شی ای از نوع کلاس HttpResponseMessage ایجاد می‌کنیم. آدرس منبع جدید نیز با استفاده از response.Headers.Location مشخص شده است. نمونه ای از پاسخ دریافت شده در سمت Client به صورت ذیل است.


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

public void PutProduct(int id, Product product)
{
    product.Id = id;
    if (!repository.Update(product))
    {
        throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
    }
}
نام متد با عبارت Put آغاز شده است. بنابراین توسط Web API برای پردازش درخواست‌های از نوع PUT در نظر گرفته می‌شود. متد قبل، دو پارامتر ورودی دارد. id برای مشخصه‌ی محصول، و محصول آپدیت شده که در پارامتر دوم قرار می‌گیرد. مقدار پارامتر id از آدرس دریافت می‌شود و مقدار پارامتر product از بدنه‌ی درخواست. به طور پیش فرض، Web API، مقدار داده هایی با نوع ساده مانند int، string و bool را از طریق route، و مقدار نوع‌های پیچیده‌تر مانند داده‌های یک کلاس را از بدنه‌ی درخواست می‌خواند.

حذف یک رکورد
حذف یک رکورد، با استفاده از درخواست‌های از نوع DELETE انجام می‌گیرد. یک مثال ساده در این مورد.
public HttpResponseMessage DeleteProduct(int id)
{
    repository.Remove(id);
    return new HttpResponseMessage(HttpStatusCode.NoContent);
}
بر اساس مستندات پروتکل HTTP، اگر منبعی که Client قصد حذف آن را دارد از پیش حذف شده است، نباید خطایی به وی گزارش شود. معمولاً در متدهایی که وظیفه‌ی حذف منبع را بر عهده دارند، کد 204 مبنی بر پردازش کامل درخواست و پاسخ خالی برگشت داده می‌شود. این کد با استفاد از مقدار NoContent برای HttpStatusCode مشخص می‌شود.

فراخوانی متدها و مدیریت کدهای وضعیت HTTP در سمت Client
حال ببینیم چگونه می‌توان از متدهای قبل در سمت Client استفاده و خطاهای احتمالی آنها را مدیریت کرد.
بهتر است مثال را برای حالتی که در آن رکوردی آپدیت می‌شود بررسی کنیم. کدهای مورد نیاز برای فراخوانی متد PutProduct در سمت Client به صورت ذیل است.
var id = $("#myTextBox").val();

$.ajax({
  url: "/api/Test/" + id,
   type: 'PUT',
   data: { Id: "1", Name: "Tomato Soup", Category: "Groceries", Price: "1.39M" },
   cache: false,
   statusCode: {
       200: function (data) {
           alert("آپدیت انجام شد");
        },
       404:
            function () {
                alert("خطا در آپدیت");
            }
      }
});
از متدهای get، getJson یا post در jQuery نمی‌توان برای عمل آپدیت استفاده نمود، چون Web API انتظار دارد تا نام فعل درخواستی، PUT باشد. اما با استفاده از متد ajax و ذکر نام فعل در پارامتر type آن می‌توان نوع درخواست را PUT تعریف کرد. خط 5 بدین منظور است. از طریق خصیصه‌ی statusCode نیز می‌توان کدهای وضعیت مختلف HTTP را بررسی کرد. دو کد 200 و 404 که به ترتیب نشان از موفقیت و عدم موفقیت در آپدیت رکورد هستند تعریف شده و پیغام مناسب به کاربر نمایش داده می‌شود.
در حالتی که آپدیت با موفقیت همراه باشد، بدنه‌ی پاسخ به شکل ذیل است.


  و در صورتی که خطایی رخ دهد، بدنه‌ی پاسخ دریافتی به صورت ذیل خواهد بود.


مطالب
مبانی TypeScript؛ Decorators
Decorators  یا تزئین کننده‌ها و ReflectDecorators، یکی از پیشنهادهای نگارش بعدی جاوا اسکریپت هستند (ECMAScript 2016) که هم اکنون قابلیت استفاده‌ی از آن‌ها در TypeScript وجود دارد.
جهت افزودن قابلیت‌های meta-programming به زبان‌های جاوا اسکریپت و TypeScript و همچنین تعریف annotations بر روی کلاس‌ها و اعضای کلاس، می‌توان از Decorators استفاده کرد. یک decorator، تعریف ویژه‌ای است که می‌تواند به تعریف یک کلاس، متد، خاصیت و یا پارامتر «متصل» شود و به صورت expression@ تعریف می‌گردد. این expression باید قابلیت فراخوانی به صورت یک متد را داشته باشد که در زمان اجرا فراخوانی خواهد شد. از Decorators در طراحی AngularJS 2 زیاد استفاده شده‌است.


نحوه‌ی فعال سازی Decorators با ES 5

این قابلیت فعلا در مرحله‌ی آزمایش به سر می‌برد؛ بنابراین برای فعال سازی آن نیاز است پارامترهای experimentalDecorators و emitDecoratorMetadata را به کامپایلر خط فرمان tsc و یا به خواص کامپایلر در فایل tsconfig.json اضافه کنید:
Command Line:
tsc --target ES5 --experimentalDecorators --emitDecoratorMetadata

tsconfig.json:
{
    "compilerOptions": {
        "target": "ES5",
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true
    }
}


بررسی انواع Decorators

در اینجا یک مثال ساده از decoratorها را مشاهده می‌کنید:
 // A simple decorator
@decoratorExpression
class MyClass { }
و ساده‌ترین فرم پیاده سازی این decoratorExpression به صورت زیر است:
function decoratorExpression(target) {
   // Add a property on target
   target.annotated = true;
}
همانطور که ملاحظه می‌کنید، یک decorator در اصل یک function است که دسترسی به target ایی را که قرار است تزئین شود، میسر می‌کند. این قابلیت بسیار شبیه است به مفهومی به نام attributes و annotations در زبان #C.
در ادامه انواع و اقسام decoratorهای ممکن را با مثال‌هایی بررسی خواهیم کرد.


Class Decorator

یک class Decorator، پیش از تعریف یک کلاس اضافه می‌شود و هدف آن، اعمال تعاریفی به سازنده‌ی کلاس است و از آن می‌توان جهت تحت نظر قرار دادن تعاریف کلاس و یا تغییر یا حتی تعویض کلی تعاریف آن استفاده کرد. یک class Decorator را نمی‌توان در سایر فایل‌های تعاریف، مانند d.ts. قرار داد.
تنها آرگومانی که به یک class Decorator ارسال می‌شود، سازنده‌ی کلاسی است که به آن اعمال شده‌است. اگر متد class Decorator مقداری را برگرداند، سبب تعویض و جایگزینی تعاریف کلاس با مقدار باگشت داده شده، می‌شود.
در ادامه دو مثال را از class Decoratorها مشاهده می‌کنید:

مثال بدون پارامتر
 function ClassDecorator(
target: Function // The class the decorator is declared on
) {
    console.log("ClassDecorator called on: ", target);
}

@ClassDecorator
class ClassDecoratorExample {
}


اگر به تصویر فوق و خروجی نهایی آن دقت کنید، مشاهده می‌کنید که یک decorator برای اجرا، نیازی به وهله سازی از آن کلاس ندارد و اجرای آن دقیقا در زمان تعریف کلاس انجام می‌شود. این اجرا به معنای تزریق کدهای تزئین کننده، به تعاریف سازنده‌ی کلاس تعریف شده، پیش از وهله سازی از آن است.

مثال با پارامتر
 function ClassDecoratorParams(param1: number, param2: string) {
return function(
  target: Function // The class the decorator is declared on
  ) {
   console.log("ClassDecoratorParams(" + param1 + ", '" + param2 + "') called on: ", target);
}
}

@ClassDecoratorParams(1, "a")
@ClassDecoratorParams(2, "b")
class ClassDecoratorParamsExample {
}
با خروجی
 ClassDecoratorParams(2, 'b') called on: function ClassDecoratorParamsExample() {
}
ClassDecoratorParams(1, 'a') called on: function ClassDecoratorParamsExample() {
}
همانطور که در این مثال مشاهده می‌کنید، چندین decorator را نیز می‌توان به تعاریف یک کلاس اعمال کرد که به آن Decorator Composition نیز می‌گویند.


Property Decorator

یک Property Decorator دقیقا پیش از تعریف یک خاصیت اضافه می‌شود و نباید در سایر فایل‌های تعاریف جانبی قرار گیرد. زمانیکه متد expression آن در runtime فراخوانی می‌شود، دو پارامتر را دریافت خواهد کرد:
الف) برای static member ها، متد سازنده‌ی کلاس و برای  instance memberها، prototype کلاس را دریافت می‌کند.
ب) نام عضو.

اگر متد expression تعریف شده، مقداری را برگرداند، به عنوان Property Descriptor آن عضو بکارگرفته می‌شود.

در مثال ذیل که متد PropertyDecorator به خاصیت name اعمال شده‌است، دو پارامتر ارسالی به آن‌را بهتر می‌توان مشاهده کرد:
 function PropertyDecorator(
target: Object, // The prototype of the class
propertyKey: string | symbol // The name of the property
) {
   console.log("PropertyDecorator called on: ", target, propertyKey);
}

class PropertyDecoratorExample {
@PropertyDecorator
name: string;
}
با خروجی
 PropertyDecorator called on: PropertyDecoratorExample {} name


Method Decorator

یک Method Decorator باید درست پیش از تعریف یک متد، قرارگیرد و نباید در سایر کلاس‌ها تعاریف نوع‌های جانبی افزوده شود. هدف از آن می‌تواند بررسی، مشاهده و تغییر رفتار یک متد باشد. به متد expression آن، سه پارامتر ارسال می‌شوند:
الف) برای static member ها، متد سازنده‌ی کلاس و برای  instance memberها، prototype کلاس را دریافت می‌کند.
ب) نام عضو
ج) Property Descriptor عضو

اگر متد تعریف شده، خروجی را برگرداند به عنوان Property Descriptor آن متد استفاده خواهد شد.

در مثال ذیل، متد تزئین کننده‌ای به نام MethodDecorator تعریف شده‌است که سه پارامتر یاد شده را در زمان اجرا دریافت می‌کند:
 function MethodDecorator(
target: Object, // The prototype of the class
propertyKey: string, // The name of the method
descriptor: TypedPropertyDescriptor<any>
) {
console.log("MethodDecorator called on: ", target, propertyKey, descriptor);
}

class MethodDecoratorExample {
   @MethodDecorator
   method() {
   }
}
با خروجی
 MethodDecorator called on: MethodDecoratorExample { method: [Function] } method { value: [Function],
writable: true,
enumerable: true,
configurable: true }

و مثالی جهت محدود ساختن آن به یک سری متد خاص که یک پارامتر عددی را دریافت می‌کنند و یک خروجی عددی نیز دارند:
 function TypeRestrictedMethodDecorator(
target: Object, // The prototype of the class
propertyKey: string, // The name of the method
descriptor: TypedPropertyDescriptor<(num: number) => number>
) {
   console.log("TypeRestrictedMethodDecorator called on: ", target, propertyKey, descriptor);
}

class TypeRestrictedMethodDecoratorExample {
   @TypeRestrictedMethodDecorator
   method(num: number): number {
      return 0;
   }
}
با خروجی
 TypeRestrictedMethodDecorator called on: TypeRestrictedMethodDecoratorExample { method: [Function] } method { value: [Function],
writable: true,
enumerable: true,
configurable: true }

و مثالی از تزئین کننده‌های متدهای استاتیک یک کلاس که در این حالت، پارامتر target از نوع متد سازنده‌ی کلاس خواهد بود و نه prototype آن:
 function StaticMethodDecorator(
target: Function, // the function itself and not the prototype
propertyKey: string | symbol, // The name of the static method
descriptor: TypedPropertyDescriptor<any>
) {
   console.log("StaticMethodDecorator called on: ", target, propertyKey, descriptor);
}

class StaticMethodDecoratorExample {
   @StaticMethodDecorator
   static staticMethod() {
   }
}
با خروجی
 StaticMethodDecorator called on: function StaticMethodDecoratorExample() {
} staticMethod { value: [Function],
writable: true,
enumerable: true,
configurable: true }


Parameter Decorator

یک Parameter Decorator باید درست پیش از تعریف یک آرگومان متد، قرارگیرد و نباید در سایر کلاس‌ها تعاریف نوع‌های جانبی افزوده شود. به متد expression آن سه پارامتر ارسال می‌شوند:
الف) برای static member ها، متد سازنده‌ی کلاس و برای  instance memberها، prototype کلاس را دریافت می‌کند.
ب) نام عضو
ج) شماره ایندکس پارامتر مدنظر در متد

از خروجی متد تزئین کننده در اینجا صرفنظر می‌شود.

در ادامه مثالی را از نحوه‌ی تعریف یک تزئین کننده‌ی پارامترها را با سه آرگومان ویژه‌ی آن، مشاهده می‌کنید:
 function ParameterDecorator(
target: Function, // The prototype of the class
propertyKey: string | symbol, // The name of the method
parameterIndex: number // The index of parameter in the list of the function's parameters
) {
   console.log("ParameterDecorator called on: ", target, propertyKey, parameterIndex);
}

class ParameterDecoratorExample {
   method(@ParameterDecorator param1: string, @ParameterDecorator param2: number) {
   }
}
با خروجی
 ParameterDecorator called on: ParameterDecoratorExample { method: [Function] } method 1
ParameterDecorator called on: ParameterDecoratorExample { method: [Function] } method 0

یک سری مثال تکمیلی
نظرات مطالب
بهبود SEO در ASP.NET MVC
نکته‌ای مهم برای کاهش SEO جماعت کپی پیست کار
اگر محتوای سایت شما عینا در سایت‌های دیگر کپی پیست شده، چگونه می‌توانید به گوگل اعلام کنید که محتوای اصلی کدام است؟ کدام یکی کپی است و کدام یک متعلق به شما است؟ برای این منظور باید ذیل مطالب خودتان تنظیمات مربوط به گوگل پلاس خود را نیز قرار دهید:
 <a rel="author" href="https://plus.google.com/your_g_plus_id?rel=author">G+</a>
سپس در گوگل پلاس خود اعلام کنید که در این سایت مشارکت دارید (در قسمت Contributor to).
اشتراک‌ها
تفاوت های موجود در Asp.Net Mvc 2,3,4,5,6

برای اینکه بتوانیم از تمام ویژگی‌های اعمال شده در یک فریمورک به نحو درست استفاده کنیم بایستی در ابتدا بدانیم که در هر ورژن چه ویژگی هایی به آن اضافه گردیده است در اینجا سیر تکاملی ویژگی‌های اعمال شده در    Asp.Net Mvc را لیست شده است .


تفاوت های موجود در Asp.Net Mvc 2,3,4,5,6
نظرات مطالب
بررسی تغییرات Blazor 8x - قسمت چهارم - معرفی فرم‌های جدید تعاملی

یک نکته‌ی تکمیلی: روش طراحی binding دو طرفه در Blazor SSR

در نکته‌ی قبل عنوان شد که مقدمات طراحی binding دو طرفه، داشتن حداقل سه خاصیت زیر در یک کامپوننت سفارشی است:

[Parameter] public T? Value { set; get; }

[Parameter] public EventCallback<T?> ValueChanged { get; set; }

[Parameter] public Expression<Func<T?>> ValueExpression { get; set; } = default!;

اگر این خواص را به کامپوننت‌های توکار خود Blazor متصل کنیم (مانند InputBox آن و مابقی آن‌ها)، نیازی به کدنویسی بیشتری ندارند و کار می‌کنند. اما اگر قرار است از یک input ساده‌ی Html ای استفاده کنیم، نیاز است ValueChanged آن‌را اینبار در متد OnInitialized فراخوانی کنیم؛ چون در زمان post-back به سرور است که مقدار آن در اختیار مصرف کننده‌ی کامپوننت قرار می‌گیرد. این مورد، مهم‌ترین تفاوت نحوه‌ی طراحی binding دوطرفه در Blazor SSR با مابقی حالات و نگارش‌های Blazor است.

بررسی وقوع post-back به سرور به دو روش زیر میسر است:

الف) بررسی کنیم که آیا HttpPost ای رخ‌داده‌است؟ سپس در همین لحظه، متد ValueChanged.InvokeAsync را فراخوانی کنیم:

[CascadingParameter] internal HttpContext HttpContext { set; get; } = null!;

protected override void OnInitialized()
{
   base.OnInitialized();

   if (HttpContext.IsPostRequest())
   {
      SetValueCallback(Value);
   }
}

private void SetValueCallback(string value)
{
   if (!ValueChanged.HasDelegate)
   {
      return;
   }

   _ = ValueChanged.InvokeAsync(value);
}

در این مثال نحوه‌ی فعالسازی ارسال اطلاعات از یک کامپوننت سفارشی را به مصرف کننده‌ی آن ملاحظه می‌کنید. اینکار در قسمت OnInitialized و فقط در صورت ارسال اطلاعات به سمت سرور، فعال خواهد شد.

ب) می‌توان در قسمت OnInitialized، بررسی کرد که آیا درخواست جاری به همراه اطلاعات یک فرم ارسال شده‌ی به سمت سرور است یا خیر؟ روش کار به صورت زیر است:

protected override void OnInitialized()
{
   base.OnInitialized();

   if (HttpContext.Request.HasFormContentType &&
       HttpContext.Request.Form.TryGetValue(ValueField.HtmlFieldName, out var data))
   {
      SetValueCallback(data.ToString());
   }
}

در اینجا از ValueField.HtmlFieldName که در نکته‌ی قبلی معرفی BlazorHtmlField به آن اشاره شد، جهت یافتن نام واقعی فیلد ورودی، استفاده شده‌است.