ASP.NET MVC #8
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: شش دقیقه


معرفی HTML Helpers

یک HTML Helper تنها یک متد است که رشته‌ای را بر می‌گرداند و این رشته می‌تواند حاوی هر نوع محتوای دلخواهی باشد. برای مثال می‌توان از HTML Helpers برای رندر تگ‌های HTML، مانند img و input استفاده کرد. یا به کمک HTML Helpers می‌توان ساختارهای پیچیده‌تری مانند نمایش لیستی از اطلاعات دریافت شده از بانک اطلاعاتی را پیاده سازی کرد. به این ترتیب حجم کدهای تکراری تولید رابط کاربری در Viewهای برنامه‌های ASP.NET MVC به شدت کاهش خواهد یافت، به همراه قابلیت استفاده مجدد از متدهای الحاقی HTML Helpers در برنامه‌های دیگر.
HTML Helpers در ASP.NET MVC معادل کنترل‌های ASP.NET Web forms هستند اما نسبت به آن‌ها بسیار سبک‌تر می‌باشند؛ برای مثال به همراه ViewState و همچنین Event model نیستند.
ASP.NET MVC به همراه تعدادی متد HTML Helper توکار است و برای دسترسی به آن‌ها شیء Html که وهله‌ای از کلاس توکار HtmlHelper می‌باشد، در تمام Viewها قابل استفاده است.


نحوه ایجاد یک HTML Helper سفارشی

از دات نت سه و نیم به بعد امکان توسعه اشیاء توکار فریم ورک، به کمک متدهای الحاقی (extension methods) میسر شده است. برای نوشتن یک HTML Helper نیز باید همین شیوه عمل کرد و کلاس HtmlHelper را توسعه داد. در ادامه قصد داریم یک HTML Helper را جهت رندر تگ label در صفحه ایجاد کنیم. برای این منظور پوشه‌ی جدیدی به نام Helper را به پروژه اضافه نمائید (جهت نظم بیشتر). سپس کلاس زیر را به آن اضافه کنید:

using System;
using System.Web.Mvc;

namespace MvcApplication4.Helpers
{
public static class LabelExtensions
{
public static string MyLabel(this HtmlHelper helper, string target, string text)
{
return string.Format("<label for='{0}'>{1}</label>", target, text);
}
}
}

همانطور که ملاحظه می‌کنید متد Label به شکل یک متد الحاقی توسعه دهنده کلاس HtmlHelper که تنها یک رشته را بر می‌گرداند، تعریف شده است. اکنون برای استفاده از این متد در View دلخواهی خواهیم داشت:

@using MvcApplication4.Helpers
@{
ViewBag.Title = "Index";
}

<h2>Index</h2>

@Html.MyLabel("firstName", "First Name:")

ابتدا فضای نام مرتبط با متد الحاقی باید پیوست شود و سپس از طریق شیء Html می‌توان به این متد الحاقی دسترسی پیدا کرد. اگر برنامه را اجرا کنید، این خروجی را مشاهده خواهیم کرد. چرا؟

Index
<label for='firstName'>First Name:</label>

علت این است که Razor، اطلاعات را Html encoded به مرورگر تحویل می‌دهد. برای تغییر این رویه باید اندکی متد الحاقی تعریف شده را تغییر داد:

using System.Web.Mvc;

namespace MvcApplication4.Helpers
{
public static class LabelExtensions
{
public static MvcHtmlString MyLabel(this HtmlHelper helper, string target, string text)
{
return MvcHtmlString.Create(string.Format("<label for='{0}'>{1}</label>", target, text));
}
}
}

تنها تغییر صورت گرفته، استفاده از MvcHtmlString بجای string معمولی است تا Razor آن‌را encode نکند.

تعریف HTML Helpers سفارشی به صورت عمومی:

می‌توان فضای نام MvcApplication4.Helpers این مثال را عمومی کرد. یعنی بجای اینکه بخواهیم در هر View  آن‌را ابتدا تعریف کنیم، یکبار آن‌را همانند تعاریف اصلی یک برنامه ASP.NET MVC، عمومی معرفی می‌کنیم. برای این منظور فایل web.config موجود در پوشه Views را باز کنید (و نه فایل web.config قرار گرفته در ریشه اصلی برنامه). سپس فضای نام مورد نظر را در قسمت namespaces صفحات اضافه نمائید:

<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="MvcApplication4.Helpers"/>
</namespaces>

به این ترتیب متدهای الحاقی تعریف شده در فضای نام MvcApplication4.Helpers،‌ در تمام Viewهای برنامه در دسترس خواهند بود.

استفاده از کلاس TagBuilder برای تولید HTML Helpers سفارشی:

using System.Web.Mvc;

namespace MvcApplication4.Helpers
{
public static class LabelExtensions
{
public static MvcHtmlString MyNewLabel(this HtmlHelper helper, string target, string text)
{
var labelTag = new TagBuilder("label");
labelTag.MergeAttribute("for", target);
labelTag.InnerHtml = text;
return MvcHtmlString.Create(labelTag.ToString());
}
}
}

در فضای نام System.Web.Mvc، کلاسی وجود دارد به نام TagBuilder که کار تولید تگ‌های HTML، مقدار دهی ویژگی‌ها و خواص آن‌ها را بسیار ساده می‌کند و روش توصیه شده‌ای است برای تولید متدهای HTML Helper. یک نمونه از کاربرد آن‌را برای بازنویسی متد MyLabel ذکر شده در اینجا ملاحظه می‌کنید.
شبیه به همین کلاس، کلاس دیگری به نام HtmlTextWriter در فضای نام System.Web.UI برای انجام اینگونه کارها وجود دارد.


نوشتن HTML Helpers ویژه، به کمک امکانات Razor

نوع دیگری از این متدهای کمکی، Declarative HTML Helpers نام دارند. از این جهت هم Declarative نامیده شده‌اند که مستقیما درون فایل‌های cshtml یا vbhtml به کمک امکانات Razor قابل تعریف هستند. تولید این نوع متدهای کمکی به این شکل نسبت به مثلا روش TagBuilder ساده‌تر است،‌ چون توسط Razor به سادگی و به نحو طبیعی‌تری می‌توان تگ‌های HTML و کدهای مورد نظر را با هم ترکیب کرد (این رفتار طبیعی و روان، یکی از اهداف Razor است).
به عنوان مثال، تعاریف همان کلاس‌های Product و Products قسمت قبل (قسمت هفتم) را در نظر بگیرید. با همان کنترلر و View ایی که ذکر شد.
سپس برای تعریف این نوع خاص از HTML Helpers/Razor Helpers باید به این نحو عمل کرد:
الف) در ریشه پروژه یا سایت، پوشه‌ی جدیدی به نام App_Code ایجاد کنید (دقیقا به همین نام. این پوشه، جزو پوشه‌های ویژه ASP.NET است).
ب) بر روی این پوشه کلیک راست کرده و گزینه Add|New Item را انتخاب کنید.
ج) در صفحه باز شده، MVC 3 Partial Page/Razor را یافته و مثلا نام ProductsList.cshtml را وارد کرده و این فایل را اضافه کنید.
د) محتوای این فایل جدید را به نحو زیر تغییر دهید:

@using MvcApplication4.Models
@helper GetProductsList(List<Product> products)
{
<ul>
@foreach (var item in products)
{
<li>@item.Name ($@item.Price)</li>
}
</ul>
}

در اینجا نحوه تعریف یک helper method مخصوص Razor را مشاهده می‌کنید که با کلمه @helper شروع شده است. مابقی آن هم ترکیب آشنای code و markup هستند که به کمک امکانات Razor به این شکل روان میسر شده است.
اکنون اگر Viewایی بخواهد از این اطلاعات استفاده کند تنها کافی است به نحو زیر عمل نماید:

@model List<MvcApplication4.Models.Product>
@{
ViewBag.Title = "Index";
}

<h2>Index</h2>

@ProductsList.GetProductsList(@Model)

ابتدا نام فایل ذکر شده بعد نام متد کمکی تعریف شده در آن. Model هم در اینجا به لیستی از محصولات اشاره می‌کند.
همچنین چون در پوشه app_code قرار گرفته، تمام Viewها به اطلاعات آن دسترسی خواهند داشت. علت هم این است که ASP.NET به صورت خودکار محتوای این پوشه ویژه را همواره کامپایل می‌کند و در اختیار برنامه قرار می‌دهد.
به علاوه در این فایل ProductsList.cshtml، باز هم می‌توان متدهای helper دیگری را اضافه کرد و از این بابت محدودیتی ندارد. همچنین می‌توان این متد helper را مستقیما داخل یک View هم تعریف کرد. بدیهی است در این حالت قابلیت استفاده مجدد از آن‌را به همراه داشتن Viewهایی تمیز و کم حجم، از دست خواهیم داد.

جهت تکمیل بحث
Turn your Razor helpers into reusable libraries


  • #
    ‫۱۲ سال و ۶ ماه قبل، دوشنبه ۱۴ فروردین ۱۳۹۱، ساعت ۰۳:۱۵
    بسیار متشکر آقای نصیری ، به شدت این سلسله مباحث را دنبال می کنم. خداقوت.
  • #
    ‫۱۲ سال و ۶ ماه قبل، سه‌شنبه ۱۵ فروردین ۱۳۹۱، ساعت ۰۵:۴۸
    مرسی خیلی عالیه لطفا ادامه بدید...
  • #
    ‫۱۲ سال و ۶ ماه قبل، جمعه ۱۸ فروردین ۱۳۹۱، ساعت ۱۸:۳۲
    استاد وحید خان نصیری
    بسیار ممنون از مطالب عالیتون
  • #
    ‫۱۲ سال و ۴ ماه قبل، شنبه ۳ تیر ۱۳۹۱، ساعت ۱۸:۳۷
    با سلام و تشکر فروان نسبت به اطلاعات کاملی که در اختیار ما قرار میدهد.
    میشه لطفی کنید توضیحاتی در مورد MvcHtmlString و در مورد MvcHtmlString.cteate بدهید. قبلا از بابت پاسخ تشکر میکنم.
  • #
    ‫۱۲ سال و ۱ ماه قبل، جمعه ۲۴ شهریور ۱۳۹۱، ساعت ۱۷:۴۱
    سلام
    در متد الحاقی "MyNewLabel" شما مقدار text رو توسط خاصیت InnerHtml به تگ نسبت داید که در این حالت متن Encode نمیشه . می‌خواستم بدونم آیا بهتر نیست از متد SetInnerText در این حالت استفاده کنیم ؟
    • #
      ‫۱۲ سال و ۱ ماه قبل، جمعه ۲۴ شهریور ۱۳۹۱، ساعت ۱۷:۵۸
      بسته به نیاز باید تصمیم گیری کرد. یک جایی Html.Raw مناسب است، جای دیگری نمونه encoded آن.
  • #
    ‫۱۲ سال و ۱ ماه قبل، جمعه ۲۴ شهریور ۱۳۹۱، ساعت ۱۹:۰۶
    سلام
    در توضیحات متد "MvcHtmlString.Create" این نوشته شده است :


    مگه این به معنی ایجاد یک رشته‌ی encoded نیست؟
    علامت "-" قبل از encoded به چه معنی است؟


    • #
      ‫۱۲ سال و ۱ ماه قبل، جمعه ۲۴ شهریور ۱۳۹۱، ساعت ۲۲:۰۳
      ناکافی توضیح داده شده. MvcHtmlString کارش «محصور سازی» یک رشته معمولی به صورت وهله‌ای از کلاس HtmlString است. چون محصور سازی شده، MSDN نوشته Html-encoded که باید می‌نوشت «Wraps the string in a class that implements IHtmlString»
      ارائه یک رشته به صورت وهله‌ای از IHtmlString سبب خواهد شد تا زمانیکه از
      <%: %>
      و یا @ استفاده می‌شود، از حالت HTML encoded محافظت شود.
      این سورس Html.Raw است:
      public IHtmlString Raw(string value)
      {
          return new HtmlString(value);
      }
      
      public IHtmlString Raw(object value)
      {
          return new HtmlString(value == null ? null : value.ToString());
      }
      و این هم سورس MvcHtmlString :
      namespace System.Web.Mvc
      {
          public sealed class MvcHtmlString : HtmlString
          {
              [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "MvcHtmlString is immutable")]
              public static readonly MvcHtmlString Empty = Create(String.Empty);
      
              private readonly string _value;
      
              public MvcHtmlString(string value)
                  : base(value ?? String.Empty)
              {
                  _value = value ?? String.Empty;
              }
      
              public static MvcHtmlString Create(string value)
              {
                  return new MvcHtmlString(value);
              }
      
              public static bool IsNullOrEmpty(MvcHtmlString value)
              {
                  return (value == null || value._value.Length == 0);
              }
          }
      }
      در اینجا داریم MvcHtmlString : HtmlString یعنی MvcHtmlString از جنس همان HtmlString ایی است که متدهای MvcHtmlString.Create و Html.Raw باز می‌گردانند.

      کاربرد MvcHtmlString عموما در بازگرداندن مقادیر از helper methods است؛ زمانیکه می‌دانید خروجی آن دارای تگ‌های html است. مثلا قرار است یک دکمه را نمایش دهد. به این ترتیب خروجی متد از encode شدن خودکار محافظت می‌شود.
      در MVC، سیستم خروجی، رشته‌هایی از جنس IHtmlString را encode نمی‌کند. این بیشتر یک قرار داد است در اینجا.
  • #
    ‫۱۱ سال و ۹ ماه قبل، پنجشنبه ۱۴ دی ۱۳۹۱، ساعت ۲۰:۳۲
    در قسمت "نوشتن HTML Helpers ویژه، به کمک امکانات Razor " چرا توی view موقع استفاده از  helper پارامتر اون رو @Model دادید... توضیح هم دادید که به لیستی از محصولات اشاره می‌کنه پس چرا وقتی  من به این شکل مینویسم جواب نمیده:
    مگه@Model چه تفاوتی داره؟
    @model List<MvcApplication4.Models.Product>
    @{
        ViewBag.Title = "Index";
    }
     
    <h2>Index</h2>
     
    @ProductsList.GetProductsList(List<MvcApplication4.Models.Product>)
    
    یا
    
    @ProductsList.GetProductsList(MvcApplication4.Models.Products)
    • #
      ‫۱۱ سال و ۹ ماه قبل، پنجشنبه ۱۴ دی ۱۳۹۱، ساعت ۲۰:۵۳
      همان اصول زبان سی شارپ اینجا هم برقرار است. آیا در حالت متداول می‌توانید برای صدا زدن یک متد و ارسال پارامتر به آن بنویسید؟
      ProductsList.GetProductsList(List<MvcApplication4.Models.Product>)
      خیر. تعریف فوق در زبان سی شارپ معتبر نیست. برای تعریف یک متد به این شکل عمل می‌شود:
      public static void GetProductsList(List<Product> list)
      {
        // ...
      }
      اما برای صدا زدن این متد استاتیک، اصول سی‌شارپ باید رعایت شود:
      ClassName.GetProductsList(...instance...)
      در اینجا وهله یا instance ایی باید به آن پاس شود نه syntax آن و ... Model@ یک وهله است.
      • #
        ‫۱۱ سال و ۹ ماه قبل، پنجشنبه ۱۴ دی ۱۳۹۱، ساعت ۲۱:۴۷
        ممنون
        فقط یه نکته هنوز برام مشخص نشده که تو کدوم قسمت وهله ای به @Model پاس داده میشه...
        تا اونجایی که من متوجه شدم توی فضای نام Models دو تا کلاس Product و Products وجود داره و اینکه @Model وهله ای از لیست محصولات(که همون Products هست) به حساب میاد، درسته؟ پس فکر کنم مشکل من بر میگرده به اینکه با ساختار List<T>class آشنایی ندارم ، به این خاطره یا چیز دیگس؟
        • #
          ‫۱۱ سال و ۹ ماه قبل، پنجشنبه ۱۴ دی ۱۳۹۱، ساعت ۲۱:۵۴
          سورس کامل مثال‌های این سری رو دریافت کنید: MVC_Samples  
          جایی که وهله‌ای از اشیاء به View متناظر ارسال می‌شود در اکشن متد مشخص شده است (return View):
          public ActionResult Index()
          {
              var products = new Products();
              return View(products);  
          }
          • #
            ‫۱۱ سال و ۹ ماه قبل، پنجشنبه ۱۴ دی ۱۳۹۱، ساعت ۲۳:۲۲
            یعنی @Model یه viewdatadictionary هست... که با این خط کد
            return view(products)
            مقادیر پارامتر ورودی در اون قرار میگیره ... درسته؟
  • #
    ‫۱۰ سال و ۱۱ ماه قبل، شنبه ۱۱ آبان ۱۳۹۲، ساعت ۱۳:۳۵
    «تعریف HTML Helpers سفارشی به صورت عمومی:
    برای این منظور فایل web.config موجود در پوشه Views را باز کنید (و نه فایل web.config قرار گرفته در ریشه اصلی برنامه). سپس فضای نام مورد نظر را در قسمت namespaces صفحات اضافه نمائید:»

    برای من برعکس بود و باید در فایل web.config در ریشه اصلی برنامه اضافه میشد تا بدون مشکل متد Html Helper اجرا شود
    البته من با VB برنامه نویسی میکنم
  • #
    ‫۱۰ سال و ۸ ماه قبل، جمعه ۲۷ دی ۱۳۹۲، ساعت ۲۲:۳۶
    سلام؛ چرا داخل html helper نمی‌تونیم از Actionlink استفاده کنیم؟ هدفم ایجاد لینک هایی ست که به یه متد(Detail) اشاره کنن همراه با Id مورد نظر برای دیدن جزییات. ممنون
    • #
      ‫۱۰ سال و ۸ ماه قبل، جمعه ۲۷ دی ۱۳۹۲، ساعت ۲۳:۱۸
      از یکی از دو روش زیر استفاده کنید:
      var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
      var url = urlHelper.Action("Home", "Index");
      و یا
      UrlHelper.GenerateUrl(null, actionName, controllerName,
                                     null, null, null, routeValues, htmlHelper.RouteCollection, 
                                     htmlHelper.ViewContext.RequestContext, true);
    • #
      ‫۹ سال و ۷ ماه قبل، یکشنبه ۱۷ اسفند ۱۳۹۳، ساعت ۱۵:۵۴
      در ورژن کنونی ASP.NET MVC دسترسی به کلاس HtmlHelper  در یک Declerative Html Helper وجود ندارد. علاوه بر روش هایی که عنوان شد، می‌توانید از فراخوانی مستقیم متد ActionLink توسط کلاسی که آن را بسط می‌دهد استفاده کنید.
      مثال:
      @using WebApplication1.Models
      @helper GetProductsList(List<Product> products)
      {
          <ul>
              @foreach (var item in products)
              {
                  <li>
                       @System.Web.Mvc.Html.LinkExtensions.ActionLink(
                                                                      ((System.Web.Mvc.WebViewPage)CurrentPage).Html,
                                                                      item.Name,
                                                                      "ActionName",
                                                                      "ControllerName", 
                                                                      new { id = item.ProductNumber },
                                                                      null)
                  </li>
              }
          </ul>
      }

      بدیهی است در اینجا به جای فراخوانی به صورت زیر
      Html.ActionLink("foo")
       این گونه فراخوانی کرده ایم:
      ActionLink(Html, "foo")
      • #
        ‫۹ سال و ۷ ماه قبل، یکشنبه ۱۷ اسفند ۱۳۹۳، ساعت ۱۶:۲۰
        در قسمت بعدی، بحث متد (helper GetProductsList(WebViewPage page, List<Product> products@ را مطالعه کنید.
        • #
          ‫۹ سال و ۷ ماه قبل، یکشنبه ۱۷ اسفند ۱۳۹۳، ساعت ۱۸:۱۳
          متشکرم
          راه حلی که در قسمت بعدی ارائه شده، بهتر و ساده‌تر است.

          در مجموع شاید بهتر باشه در ورژن‌های آتی ASP.NET MVC، تیم توسعه دهنده راهی ساده‌تر برای دسترسی به HtmlHelper‌های توکار در Declerative Html Helper ‌ها ارائه کند.

          کجا می‌توان این موضوع را بهشون گزارش داد؟
  • #
    ‫۱۰ سال و ۸ ماه قبل، شنبه ۱۹ بهمن ۱۳۹۲، ساعت ۱۶:۳۹
    سلام؛  میخوام از کلاس‌های بوت استرپ در input استفاده کنم. آیا میشه برای (Html.TextBoxFor(m => m.P1@ از کلاس‌های بوت استرپ استفاده کرد؟
    • #
      ‫۱۰ سال و ۸ ماه قبل، شنبه ۱۹ بهمن ۱۳۹۲، ساعت ۱۷:۰۶
      متد TextBoxFor چندین overload دارد برای مشخص کردن ویژگی‌های HTML مانند:
       @Html.TextBoxFor(m => m.LastName, new { @class = "class-name", placeholder = "last name" })
      در اینجا چون نام class معادل یکی از نام‌های رزرو سی‌شارپ است، یک @ ابتدای آن قرار گرفته.
  • #
    ‫۱۰ سال و ۸ ماه قبل، سه‌شنبه ۲۲ بهمن ۱۳۹۲، ساعت ۱۹:۰۸


    دلیل Null بودن رو متوجه نمی‌شم؟

    • #
      ‫۱۰ سال و ۸ ماه قبل، سه‌شنبه ۲۲ بهمن ۱۳۹۲، ساعت ۲۱:۲۵
      - فراخوانی این متد کمکی به چه نحوی بوده؟ (اکشن متد آن که Model@ را مقدار دهی می‌کند و همچنین کدهای View فراخوان ذکر نشده)
      - مثال اصلی بحث جاری از اینجا قابل دریافت است: MVC_Samples  
      در کدهای پوشه MVC-08 به HomeController و متد Index آن دقت کنید (برای مقدار دهی مدل). همچنین در View فراخوان، در پوشه Views\Home، در فایل Index.cshtml، نحوه‌ی تعریف نوع مدل را توسط model@ و استفاده از مقدار آن‌را توسط Model@، بررسی کنید. (نوع مدل با m کوچک شروع می‌شود و مقدار مدل با M بزرگ)
  • #
    ‫۱۰ سال و ۷ ماه قبل، سه‌شنبه ۱۳ اسفند ۱۳۹۲، ساعت ۱۵:۲۰
    میشه لطف کنید بگید اگر helper  رو جایی دیگه غیر از App_code  داشته باشیم، مثلا توی یک فولدر، چه جوری باید ازش استفاده کرد؟
    • #
      ‫۱۰ سال و ۷ ماه قبل، سه‌شنبه ۱۳ اسفند ۱۳۹۲، ساعت ۱۶:۵۳
      از razor generator می‌توانید استفاده کنید.
  • #
    ‫۹ سال و ۳ ماه قبل، چهارشنبه ۲۰ خرداد ۱۳۹۴، ساعت ۰۵:۴۶
    من دقیق متوجه مزیت helper‌ها نمیشم
    الان یک helper چه کاری غیر از اینکه یک متد رو از طریق HTML@ صدا میزنه میشه؟
    یک تابع نرمال هم به همین شکل میتونه همون کار رو انجام بده
    حتی گاها میتونه اطلاعات بیشتر رو هم بده مثل خط اول پایین
    @HTML5Controls.Controls.Lists.DrawList(...)
    //====
    @HTML.DrawList(...)
    • #
      ‫۹ سال و ۳ ماه قبل، چهارشنبه ۲۰ خرداد ۱۳۹۴، ساعت ۰۵:۵۴
      در این حالت (helper@) نوشتن کد HTML مابین کدهای #C ساده‌تر و منطقی‌تر به نظر می‌رسد. همچنین در اینجا امکان بررسی کدها توسط کامپایلر Razor هم هست (چون به آن صرفا به شکل یک MvcHtmlString نگاه نمی‌شود).
  • #
    ‫۷ سال و ۵ ماه قبل، سه‌شنبه ۲۲ فروردین ۱۳۹۶، ساعت ۰۱:۱۲
    من برای تمرین helper تگ img رو بصورت زیر پیاده سازی کردم :
     public static MvcHtmlString MyImage2(this HtmlHelper helper, string src, string alt, int width, int height)
      {
    var img=new TagBuilder("img");
    img.MergeAttribute("src", VirtualPathUtility.ToAbsolute(src));
    img.MergeAttribute("alt", alt);
    img.MergeAttribute("width", width.ToString());
    img.MergeAttribute("height", height.ToString());
    return MvcHtmlString.Create(img.ToString());
      }

    آیا استفاده از VirtualPathUtility.ToAbsolute(src) برای بدست آوردن آدرس تصویر که در پوشه content قرار دارد روش درستی است ؟
    من جواب گرفتم .ولی می‌خواستم بدون آیا میشه بهتر از این عمل کرد در کلاس helper
    • #
      ‫۷ سال و ۵ ماه قبل، سه‌شنبه ۲۲ فروردین ۱۳۹۶، ساعت ۰۱:۲۸
      بهتر است از UrlHelper استفاده کنید:
      var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
      var url = urlHelper.Content("~/stuff/");