如何从MY OWN HtmlHelper中访问HtmlHelper方法?

时间:2009-01-30 02:58:01

标签: asp.net-mvc html-helper

我正在为ASP.NET MVC编写自己的HtmlHelper扩展:

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
            // .....
        };

我遇到问题时,请尝试从我的HtmlHelper定义中的 中访问UrlHelper。问题是您通常访问HtmlHelper(通过Html.MethodName(...))的方式是通过View上的属性。我自己的扩展课程显然无法使用此功能。

这是ViewMasterPage(从Beta开始)的实际MVC源代码 - 定义HtmlUrl

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);

我是否错过了访问现有HtmlHelperUrlHelper实例的其他方法 - 或者我是否真的需要创建一个新实例?我确信没有太多的开销,但如果可以的话,我宁愿使用已有的那些。

4 个答案:

答案 0 :(得分:12)

在提出这个问题之前,我已经查看了一些MVC源代码,但显然我错过了这个,这就是他们为Image帮助器做的事情。

[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毕竟是正确的方法。这对我来说足够好了。


更新:来自ASP.NET MVC v1.0 Source Code的RTM代码略有不同,如评论中所述。

文件: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);
        }

答案 1 :(得分:4)

我遇到了类似的问题,并决定在视图中调用UrlHelper并将输出传递给我的HtmlHelper扩展名会更容易。在你的情况下,它看起来像:

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

如果要访问传递给您的类的现有HtmlHelper上的扩展方法,您只需要在源代码文件中导入System.Web.Mvc.Html,然后您就可以访问它们了(这就是扩展类已定义)。如果你想要一个UrlHelper,你需要实例化它,因为你得到的HtmlHelper没有它来自的ViewPage的句柄。

答案 2 :(得分:1)

如果您需要在实用程序类中创建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上下文。

答案 3 :(得分:0)

好吧,您始终可以将页面实例传递给扩展方法。我认为这比在方法中创建新实例要好得多。

您还可以在从MasterPage / ViewMasterPage派生的类上定义此方法,然后从该派生页面。这样,您就可以访问实例的所有属性,而不必传递它们。