انجام Migration بر روی صفحات ASPX

در این قسمت از این آموزش می خواهیم در رابطه با نکات مربوط به انجام Migration بر روی یک پروژه ASP.NET Web Forms از نقطه‌نظر صفحات ASPX صحبت کنیم.

انجام Migration بر روی صفحات ASPX

همانطور که می‌دانید در فریمورک ASP.NET Web Forms ما Page ها را در قالب فایل های با پسوند فایل aspx پیاده سازی می کنیم. یک Page در ASP.NET Web Forms اغلب شبیه به یک کامپوننت در Blazor پیاده‌سازی شده و از همین جهت در Migration تبدیل به یک کامپوننت در Blazor اجرا خواهد شد. ضمنا در این رابطه می توانید از بررسی تغییرات State و Component Lifecycle در Blazor دیدن کنید.

یک Component در Blazor در یک فایل با پسوند razor ساخته می‌شود، به همین جهت شما می توانید به سادگی فایل هایی که پسوند aspx را دارند را به فایلهای razor یعنی همان کامپوننت ها تبدیل کنید. برای مثال اگر در یک پروژه که با ASP.NET Web Forms نوشته شده باشد، سه فایل با نام های Details.aspxو Details.aspx.cs و Details.aspx.designer.cs تماما قابلیت دیدن جزئیات مربوط به یک محصول را ارائه بدهند می توانند به یک کامپوننت در Blazor تبدیل شوند. در زمان تبدیل شدن به یک اپلیکیشن با Blazor و طبیعتاً یک کامپوننت بسادگی Code-Behind و Markup مربوطه، به یک فایل به نام Details.razor تبدیل خواهد شد. عملیات مربوط به Razor Compilation که شبیه به چیزی است که در فایل designer.cs لحاظ شده است در فولدر obj قرار گرفته و به طور پیش فرض در Solution Explorer قابل مشاهده کرد نیست. دقت کنید که در کد زیر محتویات یک پیج در فریم ورک ASP.NET Web Forms به شما نشان داده شده است:

<%@ Page Title="Details" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Details.aspx.cs" Inherits="eShopLegacyWebForms.Catalog.Details" %>

<asp:Content ID="Details" ContentPlaceHolderID="MainContent" runat="server">

<h2 class="esh-body-title">Details</h2>

<div class="container">

<div class="row">

<asp:Image runat="server" CssClass="col-md-6 esh-picture" ImageUrl='<%#"/Pics/" + product.PictureFileName%>' />

<dl class="col-md-6 dl-horizontal">

<dt>Name </dt>

<dd>

<asp:Label runat="server" Text='<%#product.Name%>' />

</dd>

<dt>Description </dt>

<dd>

<asp:Label runat="server" Text='<%#product.Description%>' />

</dd>

<dt>Brand </dt>

<dd>

<asp:Label runat="server" Text='<%#product.CatalogBrand.Brand%>' />

</dd>

<dt>Type</dt>

<dd>

<asp:Label runat="server" Text='<%#product.CatalogType.Type%>' />

</dd>

<dt>Price </dt>

<dd>

<asp:Label CssClass="esh-price" runat="server" Text='<%#product.Price%>' />

</dd>

<dt>Picture name </dt>

<dd>

<asp:Label runat="server" Text='<%#product.PictureFileName%>' />

</dd>

<dt>Stock </dt>

<dd>

<asp:Label runat="server" Text='<%#product.AvailableStock%>' />

</dd>

<dt>Restock </dt>

<dd>

<asp:Label runat="server" Text='<%#product.RestockThreshold%>' />

</dd>

<dt>Max stock </dt>

<dd>

<asp:Label runat="server" Text='<%#product.MaxStockThreshold%>' />

</dd>

</dl>

</div>

<div class="form-actions no-color esh-link-list"> <a runat="server" href='<%# GetRouteUrl("EditProductRoute", new {id =product.Id}) %>' class="esh-link-item">Edit </a> | <a runat="server" href="~" class="esh-link-item">Back to list </a> </div>

</div>

</asp:Content>

علاوه بر این موضوع Code-Behind مربوط به این فایل می تواند شبیه به چیزی باشد که در قسمت زیر مشاهده می کنید:

https://virgool.io/d/rg4ov7k9aesg/usingeShopLegacyWebForms.Models;
https://virgool.io/d/rg4ov7k9aesg/usingeShopLegacyWebForms.Services;
https://virgool.io/d/rg4ov7k9aesg/usinglog4net;
https://virgool.io/d/rg4ov7k9aesg/usingSystem;
https://virgool.io/d/rg4ov7k9aesg/usingSystem.Web.UI;
https://virgool.io/d/rg4ov7k9aesg/namespaceeShopLegacyWebForms.Catalog%7B
publicpartialclassdetails:System.Web.UI.Page{
https://virgool.io/d/rg4ov7k9aesg/privatestaticreadonlyILog_log=LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
https://virgool.io/d/rg4ov7k9aesg/protectedCatalogItemproduct;
https://virgool.io/d/rg4ov7k9aesg/publicICatalogServiceCatalogService%7B
https://virgool.io/d/rg4ov7k9aesg/get;
https://virgool.io/d/rg4ov7k9aesg/set;
https://virgool.io/d/rg4ov7k9aesg/%7D
https://virgool.io/d/rg4ov7k9aesg/protectedvoidPage_Load(objectsender,EventArgse)%7B
https://virgool.io/d/rg4ov7k9aesg/varproductId=Convert.ToInt32(Page.RouteData.Values[
https://virgool.io/d/rg4ov7k9aesg/_log.Info($
https://virgool.io/d/rg4ov7k9aesg/product=CatalogService.FindCatalogItem(productId);
https://virgool.io/d/rg4ov7k9aesg/this.DataBind();
https://virgool.io/d/rg4ov7k9aesg/%7D
https://virgool.io/d/rg4ov7k9aesg/%7D
}
https://virgool.io/d/rg4ov7k9aesg/usingeShopLegacyWebForms.Models;

زمانی که پروژه به Blazor تبدیل می‌شود می‌توان به سادگی این Page به کدی که در قسمت زیر مشاهده می کنید، تبدیل نمود:

@page "/Catalog/Details/{id:int}"

@inject ICatalogService CatalogService

@inject ILogger < Details > Logger

</pre>

<pre><h2 class="esh-body-title">Details</h2>

<div class="container">

<div class="row">

<img class="col-md-6 esh-picture" src="@($"/Pics/{_item.PictureFileName}")">

<dl class="col-md-6 dl-horizontal">

<dt> Name </dt>

<dd> @_item.Name </dd>

<dt> Description </dt>

<dd> @_item.Description </dd>

<dt>

Brand

</dt>

<dd> @_item.CatalogBrand.Brand </dd>

<dt> Type </dt>

<dd> @_item.CatalogType.Type </dd>

<dt> Price </dt>

<dd> @_item.Price </dd>

<dt> Picture name </dt>

<dd> @_item.PictureFileName </dd>

<dt> Stock </dt>

<dd> @_item.AvailableStock </dd>

<dt> Restock </dt>

<dd> @_item.RestockThreshold </dd>

<dt> Max stock </dt>

<dd> @_item.MaxStockThreshold </dd>

</dl>

</div>

<div class="form-actions no-color esh-link-list"> <a href="@($"/Catalog/Edit/{_item.Id}")" class="esh-link-item"> Edit </a>

| <a href="/" class="esh-link-item"> Back to list </a>

</div>

</div></pre>

<pre>

@code {

private CatalogItem _item;

[Parameter] public int Id {

get;

set;

}

protected override void OnInitialized() {

Logger.LogInformation("Now loading... /Catalog/Details/{Id}", Id);

_item = CatalogService.FindCatalogItem(Id);

}

}

دقت کنید در این مثال هم کد و هم Markup هر دو در یک فایل یکسان قرار گرفتند. تمامی سرویس های مورد نیاز با استفاده از @inject به درون این فایل تزریق می شود. علاوه بر این با استفاده از دستور @page میتوان برای این پیج یک Route تعریف نمود. علاوه بر این موضوع یک Route می تواند یک پارامتر نیز داشته باشد که به صورت {id} تعریف شده ، در این مثال لحاظ شده است. در این مثال نوع داده پارامتر id نیز به صورت int لحاظ شده است. علیرغم چیزی که در ASP.NET Web Forms وجود داشت، در یک کامپوننت از Blazor شما می توانید Route و پارامترهای مورد نیاز آن را نیز به سادگی و لحاظ نمایید.

مورد آخر اینکه بعضی اوقات کنترل های موجود در ASP.NET Web Forms یک معادل دقیق در Blazor ندارند اما گاهی نیز به سادگی می توان یک معادل HTML برای آنها لحاظ کرد. برای مثال دستور <asp:Label /> را می‌توان به سادگی با عنصر عنصر <label> در HTML جایگزین کرد. ضمنا برای یادگیری HTML می‌تواند از بسته ی آموزش ویدئویی HTML5 استفاده کنید.

انجام Model Validation در Blazor

اگر کد نوشته شده در فریم ورک ASP.NET Web Forms شامل Validation می‌باشد، به سادگی می توانید این Validation را به درون برنامه Blazor انتقال بدهید. با استفاده از Blazor بدون نیاز به هیچگونه کد جاوا اسکریپت خاصی می توانید Validation Logic برنامه را از پروژه ASP.NET Web Forms به درون پروژه Blazor انتقال بدهید. این کار با استفاده از Data Annotation ها انجام می شود. در رابطه با Data Annotation می توانید از بسته ی آموزش ویدئویی Attribute ها در سی شارپ دیدن کنید.

برای مثال در فایلی با نام Create.aspx ما اقدام به ایجاد کردن Validation ساده در زمان ورود داده ها توسط کاربر کرده ایم .این موضوع در کد زیر نشان داده شده است :

</pre>

<pre><div class="form-group">

<label class="control-label col-md-2">Name</label>

<div class="col-md-3">

<asp:TextBox ID="Name" runat="server" CssClass="form-control"></asp:TextBox>

<asp:RequiredFieldValidator runat="server" ControlToValidate="Name" Display="Dynamic" CssClass="field-validation-valid text-danger" ErrorMessage="The Name field is required." />

</div>

</div>></pre>

<pre>

حال به سادگی می‌توانیم با استفاده از Edit Form انجام Validation را بر روی داده های کاربران لحاظ نمایید. این کار را می توانید در فایلی با نام Create.razor کد های آن در زیر آمده، مشاهده کنید:

<EditForm Model="_item" OnValidSubmit="@...">

<DataAnnotationsValidator />

<div class="form-group">

<label class="control-label col-md-2">Name</label>

<div class="col-md-3">

<InputText class="form-control" @bind-Value="_item.Name" />

<ValidationMessage For="(() => _item.Name)" />

</div>

</div>

...

</EditForm>

استفاده کردن از Data Annotation ها یک روش بسیار معمول برای لحاظ کردن Validation می‌باشد پیاده سازی Validation با استفاده از یک کامپوننت به نام Data Annotations Validator نیز امکان پذیر است. در این رابطه توصیه می‌کنیم از بسته ی آموزش ویدئویی بلیزر (Blazor) پیشرفته و ساخت برنامه های تجاری دیدن بفرمایید.