有没有办法动态包装/拦截HtmlHelper扩展方法。想想装饰模式

时间:2011-09-21 22:54:46

标签: asp.net asp.net-mvc asp.net-mvc-3 razor html-helper

我想包装/拦截System.Web.Mvc.Html中提供的HtmlHelper扩展方法(TextBox,Hidden等),以便在2个单独的用例中重用相同的部分视图。 部分:

@model BlogEntry

@Html.TextBoxFor(t => t.Title)
@Html.TextAreaFor(t => t.Body)
@* Etc *@

Partial的调用者将知道上下文(即是否覆盖或离开MS imp)。

覆盖的原因是多种多样的。例如:在JQuery模板中使用,其中value属性的输出在上面的示例中为“$ {Title}”或者添加Html5元数据。

2 个答案:

答案 0 :(得分:3)

我不确定您对添加自己的扩展方法的顾虑是什么 - 为什么您必须“创建自己的基本视图页面并完全接管”。您可以像在内置帮助程序中一样在任何页面中调用自定义帮助程序:

@Html.TextBoxFor(x => x.Name)
@Html.MyTextBoxFor(x => x.Name)

此外,您可以在方法中添加某种标志参数,以控制它是执行默认功能还是自定义功能。

创建自己的扩展方法时,您必须更改签名或方法名称。

我曾经使用过独特的名字,但最终发现我真的希望能够从默认值中快速辨别出我自己的实现,所以我有时会使用:

@Html.Custom().TextBoxFor(…
@Html.Custom().TextAreaFor(…

基本上,您创建了一个新的扩展方法,该方法需要HtmlHelper<T>并返回CustomHelpers<T>

    public static CustomHelpers<TModel> Custom<TModel>(this HtmlHelper<TModel> html)
    {
        return new CustomHelpers<TModel>(html);
    }

CustomHelpers<T>类定义了您自己的所有实现:

    public class CustomHelpers<TModel>
    {
        private readonly HtmlHelper<TModel> _html;

        public CustomHelpers(HtmlHelper<TModel> html) { _html = html; }

        public MvcHtmlString TextBoxFor<TProperty>(Expression<Func<TModel, TProperty>> expression)
        {
            // because you have a reference to the "native" HtmlHelper<TModel>, you
            // can use it here and extend or modify the result, almost like a decorator;
            // you can get the "native" result by calling _html.TextBoxFor(expression)
        }

因此,TextBoxFor的“覆盖”可以从部分视图中接收一个标志,以确定它是返回本机结果还是特定于上下文的内容。

同样,CustomHelpers<T>类完全是可选的。您将添加一个标志参数或类似于自定义助手的签名,因此您不会与现有助手发生冲突。

它带来的好处是可能为你的帮助者命名。你可以:

@Html.TextBoxFor(…
@Html.JQuery().TextBoxFor(…
@Html.Mobile().TextBoxFor(…

答案 1 :(得分:0)

无法拦截对内置辅助扩展方法的调用。但是,您可以编写自己的扩展方法,根据上下文执行正确的操作。