Как получить доступ к методам HtmlHelper из МОЕГО СОБСТВЕННОГО HtmlHelper? - PullRequest
9 голосов
/ 30 января 2009

Я пишу свое собственное расширение 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 экземплярам - или мне действительно нужно создать новый? Я уверен, что не слишком много накладных расходов, но я бы предпочел использовать уже существующие, если смогу.

Ответы [ 4 ]

12 голосов
/ 30 января 2009

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

[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);
        }
4 голосов
/ 30 января 2009

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

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

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

1 голос
/ 07 августа 2009

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

string url = "~ / content / images / foo.jpg";

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

  string absoluteUrl = urlHelper.Content(url);

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

0 голосов
/ 30 января 2009

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

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

...