Как мне получить доступ к методам HtmlHelper из МОЕГО СОБСТВЕННОГО HtmlHelper?

StackOverflow https://stackoverflow.com/questions/494345

  •  20-08-2019
  •  | 
  •  

Вопрос

Я пишу свое собственное расширение HtmlHelper для ASP.NET MVC:

public static string CreateDialogLink (this HtmlHelper htmlHelper, string linkText, 
                                      string contentPath)
        {
            // fix up content path if the user supplied a path beginning with '~'
            contentPath = Url.Content(contentPath);  // doesn't work (see below for why)

            // create the link and return it
            // .....
        };

Где у меня возникают проблемы, так это при попытке получить доступ UrlHelper От внутри определение моего HtmlHelper.Проблема в том, что способ, которым вы обычно получаете доступ HtmlHelper (через Html.MethodName(...) ) осуществляется через свойство в представлении.Очевидно, что это недоступно для меня из моего собственного класса расширения.

Это фактический исходный код MVC для ViewMasterPage (по состоянию на бета-версию) - который определяет Html и Url.

public class ViewMasterPage : MasterPage
    {
        public ViewMasterPage();

        public AjaxHelper Ajax { get; }
        public HtmlHelper Html { get; }
        public object Model { get; }
        public TempDataDictionary TempData { get; }
        public UrlHelper Url { get; }
        public ViewContext ViewContext { get; }
        public ViewDataDictionary ViewData { get; }
        public HtmlTextWriter Writer { get; }
    }

Я хочу иметь возможность доступа к этим свойствам внутри HtmlHelper.

Лучшее, что я придумал, это это (вставить в начале CreateDialogLink способ)

HtmlHelper Html = new HtmlHelper(htmlHelper.ViewContext, htmlHelper.ViewDataContainer);
UrlHelper Url = new UrlHelper(htmlHelper.ViewContext.RequestContext);

Мне не хватает какого-то другого способа получить доступ к существующему HtmlHelper и UrlHelper экземпляры - или мне действительно нужно создать новый?Я уверен, что накладных расходов не так уж много, но я бы предпочел использовать уже существующие, если смогу.

Это было полезно?

Решение

Прежде чем задать этот вопрос, я просмотрел часть исходного кода MVC, но, очевидно, я пропустил это, как они делают это для Image helper .

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#", Justification = "The return value is not a regular URL since it may contain ~/ ASP.NET-specific characters")]
        public static string Image(this HtmlHelper helper, string imageRelativeUrl, string alt, IDictionary<string, object> htmlAttributes) {
            if (String.IsNullOrEmpty(imageRelativeUrl)) {
                throw new ArgumentException(MvcResources.Common_NullOrEmpty, "imageRelativeUrl");
            }

            UrlHelper url = new UrlHelper(helper.ViewContext);
            string imageUrl = url.Content(imageRelativeUrl);
            return Image(imageUrl, alt, htmlAttributes).ToString(TagRenderMode.SelfClosing);
        }

Похоже на создание экземпляра нового UrlHelper в конце концов, это правильный подход.Для меня этого достаточно.


Обновить: RTM - код из ASP.NET Исходный код MVC версии v1.0 немного отличается, как указано в комментариях.

Файл:MVC\src\MvcFutures\Mvc\ImageExtensions.cs

 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#", Justification = "The return value is not a regular URL since it may contain ~/ ASP.NET-specific characters")]
        public static string Image(this HtmlHelper helper, string imageRelativeUrl, string alt, IDictionary<string, object> htmlAttributes) {
            if (String.IsNullOrEmpty(imageRelativeUrl)) {
                throw new ArgumentException(MvcResources.Common_NullOrEmpty, "imageRelativeUrl");
            }

            UrlHelper url = new UrlHelper(helper.ViewContext.RequestContext);
            string imageUrl = url.Content(imageRelativeUrl);
            return Image(imageUrl, alt, htmlAttributes).ToString(TagRenderMode.SelfClosing);
        }

Другие советы

Я столкнулся с аналогичной проблемой и решил, что было бы проще просто вызвать UrlHelper в представлении и передать выходные данные в мое расширение HtmlHelper.В вашем случае это выглядело бы как:

<%= Html.CreateDialogLink( "text", Url.Content( "~/...path.to.content" ) ) %>

Если вы хотите получить доступ к методам расширения в существующем HtmlHelper, который передается в ваш класс, вам нужно будет только импортировать System.Web.Mvc.Html в вашем файле исходного кода, и вы получите к ним доступ (именно там определены классы расширений).Если вам нужен UrlHelper, вам нужно создать его экземпляр, поскольку у получаемого вами HtmlHelper нет дескриптора для ViewPage, с которой он поступает.

Если вам нужно создать UrlHelper в служебном классе, вы можете сделать следующее :

url-адрес строки = "~/content/images/foo.jpg";

  var urlHelper = new UrlHelper(new RequestContext(
                  new HttpContextWrapper(HttpContext.Current), 
                  new RouteData()), RouteTable.Routes);

  string absoluteUrl = urlHelper.Content(url);

Это позволяет вам использовать маршрутизацию или '~ expansion' вдали от контекста MVC.

Что ж, вы всегда можете передать экземпляр страницы методу расширения.Я думаю, что это гораздо лучший способ сделать это, чем создавать новые экземпляры в вашем методе.

Вы также могли бы определить этот метод в классе, который является производным от MasterPage / ViewMasterPage, а затем вывести страницу из этого.Таким образом, у вас есть доступ ко всем свойствам экземпляра, и вам не нужно передавать их по кругу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top