ایجاد Tag Helper در ASP.NET MVC
شناسه پست: 1217
بازدید: 1453

چکیده: Tag Helperها در ASP.NET Core 1.0/MVC 6 به شما کمک می کند تا در سمت سرور بتوانید محتوای html ایجاد کرده و از آن در Razor View ها استفاده نمایید. این کار باعث می شود تا View  واضحتر به نظر برسد و راحت تر قابل نگه داری و مدیریت باشد.

ASP.NET MVC 6 از dependency injection، تعریف مدلها به صورت جدا از کنترلرها و خیلی از ویژگی های دیگر پشتیبانی می نماید.

در این مقاله ما قصد داریم ویژگی دیگری از MVC 6 به نام Tag Helper را مورد بررسی قرار دهیم.

قسمت 1: Tag Helper

Tag Helper چیست؟

Tag Helper یک ویژگی جدید در ASP.NET MVC 6 است که منجربه ایجاد المنتهای html در سمت سرور و استفاده از آنها در فایلهای MVC Razor View می شود. اینها آبجکتهایی هستند که به مدلها Bind می شوند و بر اساس این خصوصیات، المنتهای HTML  به صورت داینامیک render می شوند. ما آبجکتهای tag helper های توکار مانند آبجکتهای زیر داریم:

  • asp-action – برای اکشن متدها
  • asp-route-id – برای route expression
  • asp-validation-summary – برای اعتبارسنجی ها
  • asp-for – برای اتصال به مدلها
  • و غیره

مزیت این tag helper ها این است که باعث می شود viewها در MVC واضحتر و تمیزتر به نظر برسند.

مزیت های Tag Helper

از آنجایی که Tag helper ها توسعه HTML را به صورت کاربرپسند ارائه می دهد و مانند HTML استاندارد به نظر می رسند، از این رو طراحان front-end که با فریم روک و کتابخانه های JavaScript  و CSS و غیره کار میکنند، در نتیجه میتوانند به آسانی View  را بدون دانستن زبان #C تغییر و یا بروزرسانی نمایند.

Visual Studio 2015 برای Tag helper ها در حالی که از آنها در View استفاده مینماید، intellisense ارائه میدهد.

Tag helper کدهای معتبر و قابل استفاده مجدد بهتری را ارائه میدهد که در زمان مورد نیاز میتواند بین view های مختلف ایجاد شده مورد استفاده قرار گیرد.

تفاوت بین Tag helper ها و متدهای  Html Helper در ورژن های قبلی MVC چیست؟

در ورژن های قبلی MVC (ورژن 5 و پایینتر)، ما اکستنشن متد های Html helper را داریم. اینها بر اساس پارامترهای پاس داده شده به آنها به عنوان متدهای قابل اجرا در Razor View فراخوانی میشوند. ما از نماد @ در Razor view برای فراخوانی Html helper ها استفاده مینماییم. این نماد نشانگر شروع فراخوانی متد در View میباشد.

syntax زیر را در نظر بگیرید:

@Html.LabelFor(model => model.Salary, htmlAttributes: new { @class = "control-label col-md-2" })

 

 

در کد بالا ما از LabelFor html helper استفاده میکنیم. این با استفاده از lambda expression به خصوصیت Salary  درون model نتصل شده است. پارامتر پاس شده دوم یک آبجکت anonymous  می باشد که شامل خاصیت @class می باشد. ما به این شیوه آن را تعریف نمودیم به این دلیل که class یک کلمه استاندارد در زبان C# میباشد. این پیچیدگی کدنویسی را افزایش میدهد.

در کد بالا ما از LabelFor html helper استفاده میکنیم. این با استفاده از lambda expression به خصوصیت Salary  درون model نتصل شده است. پارامتر پاس شده دوم یک آبجکت anonymous  می باشد که شامل خاصیت @class می باشد. ما به این شیوه آن را تعریف نمودیم به این دلیل که class یک کلمه استاندارد در زبان #C میباشد. این پیچیدگی کدنویسی را افزایش میدهد. در این مورد، اگر توسعه دهنده front-end دانشی از زبان #C نداشته باشد و قصد داشته باشد View که شامل html helper است را تغییر دهد امکان دارد سردرگم شده و دچار آشفتگی گردد.

ولی از سویی دیگر Tag Helper ها با المنتهای HTML  یکپارچه شده و intellisense ارائه میدهند. مهمترین ویژگی Tag Helper ها این است که آنها میتوانند مستقل از C# syntax باشند.

خط زیر را در نظر بگیرید:

<label asp-for=""CategoryId"" class=""col-md-2" control-label"=""></label>

 

 

در کد بالا، asp-for یک tag helper می باشد که به فیلد CategoryId پاس داده شده به view در model متصل می باشد. این مستقل از زبان برنامه نویسی #C می باشد.

چطور Tag Helperها در MVC 6 مدیریت میشوند؟

در MVC 6 ما باید از اسمبلی Microsoft.AspNet.Mvc.TagHelpers استفاده نماییم. این برای مدیریت تمام tag helper های توکار در اپلیکیشن استفاده می شود. برای این منظور در اپلیکشین MVC  در پوشه View ها، باید یک MVC View Imports Page به نام _ViewImports.cshtml اضافه نمایید. در این page از addTagHelper@ برای افزودن اسمبلی Microsoft.AspNet.Mvc.TagHelpers استفاده مینماییم. در پروژه، اگر ما tag helper های سفارشی در پروژه میسازیم باید اسمبلی پروژه را در فایل _ViewImports.cshtml اضافه نماییم.

قسمت 2: ایجاد Tag Helper سفارشی

ما پروژه خود را با استفاده از visual studio 2015 میسازیم.

مرحله 1: Visual Studio 2015 را باز کنید و مانند تصویر زیر یک ASP.NET Web Application جدید بسازید:

tag helper در mvc

نام آن را MVC6_TagHelpers بگذارید. روی ok کلیک کنید. سپس پنجره زیر نمایش داده خواهد شد. Empty template را انتخاب نمایید:

empty template

مرحله 2: پروژه شامل فایلی به نام project.json می باشد. ما باید dependencie های  ضروری برای ایجاد اپلیکیشن MVC را همانند شکل زیر در این فایل اضافه نماییم:

"dependencies": {
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "Microsoft.AspNet.Razor": "4.0.0-rc1-final",
    "Microsoft.AspNet.Mvc.Razor": "6.0.0-rc1-final",
    "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final",
    "Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final",
    "Microsoft.Extensions.CodeGenerators.Mvc":"1.0.0-rc1-final",  
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final"
  },

 

اینجا ما از  Microsoft.AspNet.Mvc و Microsoft.AspNet.Mvc.TagHelpers استفاده میکنیم.

مرحله 3: همچنین ما یک فایل به نام Startup.cs در پروژه داریم. این کلاس یک نقطه شروع برای اپلیکیشن MVC  است. ما کدهای زیر را در متدهای ()ConfigureServices و ()Configure برای استفاده از سرویس MVC  و Route اضافه مینماییم (قسمت های برجسته):

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
}
 
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app)
{
    app.UseIISPlatformHandler();
 
    app.UseMvc(routes =>
    {
        routes.MapRoute(name:"default",template:"{controller=Home}/{action=Index}/{id?}");
    });
}

 

مرحله 4: در پروژه، پوشه های Models, Views و Controllers را اضافه نمایید. کلاسهای زیر رادر پوشه Models با ایجاد کردن یک فایل کلاس در آن اضافه نمایید:

using System.Collections.Generic;
 
namespace MVC_TagHelper.Models
{
    public class Product
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
 
        public decimal Price { get; set; }
    }
 
    public class ProductStore : List
    {
        public ProductStore()
        {
            Add(new Product() { ProductId = 1, ProductName = "P1",Price=3000 });
            Add(new Product() { ProductId = 2, ProductName = "P2", Price = 3100 });
            Add(new Product() { ProductId = 3, ProductName = "P3", Price = 3400 });
            Add(new Product() { ProductId = 4, ProductName = "P4", Price = 3700 });
            Add(new Product() { ProductId = 5, ProductName = "P5", Price = 4000 });
            Add(new Product() { ProductId = 6, ProductName = "P6", Price = 3200 });
        }
    }
}

 

کد بالا یک کلاس موجودیت Product  و یک کلاس ProductStore  را تعریف مینماید.

مرحله 5: در پوشه Controllers، یک کنترلر اضافه نمایید و نامش را HomeController.cs بگذارید و کدهای زیر را درون آن قرار دهید:

 

using Microsoft.AspNet.Mvc;
using MVC_TagHelper.Models;
 
// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
 
namespace MVC_TagHelper.Controllers
{
    public class HomeController : Controller
    {
        // GET: //
        public IActionResult Index()
        {
            var products = new ProductStore();
            return View(products);
        }
    }
}

 

اکشن متد index، لیست محصولات را برمی گرداند.

مرحله 6: در پروژه یک پوشه جدید به نام CustomTagHelper اضافه نمایید. در این پوشه، یک فایل کلاس جدید به نام TableTagHelper.cs اضافه نمایید. سپس کدهای زیر را درون آن قرار دهید:

using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.TagHelpers;
using System.Collections;
using System.Text;
using System.Threading.Tasks;
 
using System.Reflection;
 
namespace MVC_TagHelper.CustomTagHelper
{
    //1.
    [HtmlTargetElement("table",Attributes ="generate-rows, source-model")]
    public class TableTagHelper : TagHelper
    {
        //2.
        [HtmlAttributeName("generate-rows")]
        public int RepeatCount { get; set; }
        //3.
        [HtmlAttributeName("source-model")]
        public ModelExpression DataModel { get; set; }
        //4.
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            //4a
             List model = DataModel.Model as List;
            //4b
            if (model == null)
            {
                return;
            }
            else
            {
             //4c
                StringBuilder sb = new StringBuilder();
                //4d
                foreach (var m in model.Take(RepeatCount))
                {
                    PropertyInfo[] properties = m.GetType().GetProperties();
  
                     
                    //4e
                    string html = "";
                    for (int i = 0; i < properties.Length; i++)
                    {
                        html += "" + m.GetType().GetProperty(properties[i].Name).GetValue(m, null) + "";
                    }
                    html += "";
 
                    sb.Append(html);
                }
 
                //4f
                output.Content.SetHtmlContent(sb.ToString());
            }
        }
    }
}

 

کد بالا شامل مشخصات زیر میباشد (توجه داشته باشید که شماره خطوط با شماره های مشخص شده در کامنت ها در کد بالا مطابقت دارد):

  1. کلاس TableTagHelper از کلاس TagHelper ارث بری کرده است. کلاس TagHelper  برای اعمال نمودن HTML attribute بر روی المنت HTML استفاده شده است. در این مثال، ما HtmlTergetElement attribute را روی کلاس TableTagHelper  اعمال نموده ایم. این attribute  اولین پارامتر را به عنوان نام المنت مورد نظر دریافت میکند که در این مثال المنت مورد نظر، table میباشد. دومین پارامتر، پارامتر attribute  میباشد که باید بر روی المنت مورد نظر برای اجرا اعمال شوند. در این مثال ما generate-rows  و source-model را تعیین نموده ایم. این attribute ها روی المنت table  اجرا میشوند.
  2. ویژگی RepeatCount  که برای تعیین تعداد سطرهای قابل نمایش در جدول استفاده میشود.
  3. ویژگی DataModel  که با پاس دادن LINQ expression توسط کلاس ModelExpression مورد استفاده قرار میگیرد. در این مثال ما، DataModel آبجکت مدل پاس داده شده به Razor View میبلشد.
  4. متد ()ProcessAsync از کلاس پایه TagHelper که شامل عملیات برای تولید Html میباشد override شده است. این متد دو پارامتر میگیرد. اولین پارامتر، آبجکت TagHelperContext میباشد که برای اجرای TagHelper  در context کنونی میباشد. زمانی که TagHelper  اجرا شد کلاس TagHelperOutput که دومین پارامتر این متد میباشد برای تعریف خروجی Html  مورد استفاده قرار میگیرد.

لطفا کامنتهای 4a تا 4f را در کد بررسی نمایید:

a. این خط مدل پاس داده شده به TagHelper که روی المنت مورد نظر در Razor view اعمال شده است را میخواند.

b. این خط بررسی مینماید که اگر مدل پاس داده شده به View  برابر با null است سپس متد return میشود.

c. یک نمونه از کلاس StringBuilder را تعریف مینماید که شامل المنتهای HTML بعد از اجرا خواهد بود.

d. به تعداد رکوردهایی که در ویژگی RepeatCount مشخص شده است بر روی مدل پاس داده شده پیمایش صورت میگیرد و روی آنها عملیات مورد نظر انجام میشود انجام میشود.

e. سطرها و سلولهای مورد نظر را به همراه مقادیر موجود در Model را برای المنت Table تولید میکند.

f. رشته HTML تولید شده به عنوان محتوای HTML به کلاس TagHelperOutput پاس داده میشود.

مرحله 7: برای استفاده TagHelper، یک فایل _ViewImports.cshtml در پوشه View ها اضافه نمایید و کد زیر را درون آن قرار دهید:

@using MVC_TagHelper;
@using MVC_TagHelper.Models;
 
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
@addTagHelper "*, MVC6_TagHelpers"

 در کد بالا ما tag helper های توکار را با استفاده از اسمبلی Microsoft.AspNet.Mvc.TagHelpers اضافه کردیم و برای اجرای Tag helper سفارشی مورد نظر، ما باید اسمبلی اپلیکیشن را اضافه نماییم که در اینجا اسمبلی اپلیکیشن،MVC6_TagHelpers میباشد.

مرحله 8: در پوشه View ، یک پوشه جدید به نام Home ایجاد نمایید. در این پوشه یک MVC View Page به نام Index.html اضافه نمایید. در این View، تگ مورد نظر را اضافه نمایید. زمانی که ما tag helper ها را میخواهیم اضافه نماییم مزیت استفاده از TagHelper  را در شکل زیر میتوانید مشاهده نمایید:

intellisense در tag helper

کد درون View را با کد زیر تکمیل نمایید:

@model IEnumerable<mvc_taghelper.models.product>
 
<style type=""text/css"">
    table, td {
       border:double;
      }
</style>
 
  
 
</mvc_taghelper.models.product>

 

برنامه را اجرا نمایید. سطرهای جدول بر اساس رکوردهای موجود در مدل توسط ویژگی generate-rows و source-model برای نمایش داده ها در جدول مانند شکل زیر نمایش داده میشود:

خروجی tag helper

نتیجه گیری

Tag Helper ها در ASP.NET Core 1.0 و MVC 6 کار را برای ایجاد المنتهای سفارشی در سمت سرور و استفاده از آنها در Razor View ها راحت میکند. این باعث میشود که View  تمیزتر و واضخ تر بود و قابلیت نگه داری بهتری داشته باشد.

برای دانلود سورس برنامه اینجا کلیک نمایید.

نویسنده

امید عباسی
من امید عباسی هستم. سالهاست که در زمینه برنامه نویسی با تکنولوژی دات نت فعالیت میکنم و عاشق این هستم که تجربیات و دانش خودم را در این زمینه با دیگران به اشتراک بزارم. خیلی دوست دارم که نظر و انتقاد خودتون رو در مورد این نوشته برای من بنویسید تا بتونم در آینده، مطالب بهتر و ارزشمندتری را برای شما فراهم کنم. در صورت داشتن هرگونه سوال هم در قسمت دیدگاه ها میتونید با بنده در ارتباط باشید