【问题标题】:Is there a way to dynamically wrap/intercept HtmlHelper extension methods. Think decorator pattern有没有办法动态包装/拦截 HtmlHelper 扩展方法。想想装饰器模式
【发布时间】:2011-11-22 09:22:14
【问题描述】:

我想包装/拦截 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 元数据。

【问题讨论】:

  • 如果您需要这样做,说明您的设计有问题,还有另一种方法可以实现。
  • 试图为客户端和服务器模板重复使用相同的 html 标记是不好的设计?
  • 不,不是。糟糕的设计是试图拦截对标准 html 助手的调用。
  • 我会让 Action 方法教 HtmlHelper 上下文。然后它可以决定渲染什么,你可以使用相同的视图。
  • 为什么不创建自己的助手来包装 MS 助手并实现您的自定义逻辑?我真的很喜欢将渲染切换为文字 html 或 jQuery 模板的想法。

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


【解决方案1】:

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

@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&lt;T&gt; 类定义了您自己的所有实现:

    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&lt;T&gt; 类是完全可选的。您将添加一个标志参数或类似于自定义助手签名的内容,因此您不会与现有助手发生冲突。

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

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

【讨论】:

  • 它还有助于在命名空间System.Web.Mvc.Html中声明您的自定义助手
  • Jay 我真的很喜欢你实现辅助方法的方式。
  • 关键是重新使用现有的视图,而不必通过将它们更改为自定义。目前,似乎只能通过黑客攻击,请参阅我对@marcind 的评论。顺便说一句,如果你去自定义,而不从 HtmlHelper 继承,那么一切都需要重新实现。您的技术适用于其他场景,但可能更好地从 HtmlHelper 或 HtmlHelper 恕我直言。
【解决方案2】:

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

【讨论】:

  • 拦截是错误的词。我想我遇到的 1 个问题是 HtmlHelper 功能是作为扩展方法实现的,据说这样您就可以实现自己的 TextBox 版本等,但是没有简单的方法可以“覆盖”或使用您自己的 CustomHelper 而无需创建您自己的基本视图页面并完全接管。作为一个黑客,我正在考虑做类似的事情:@{ Html = ViewBag.Html?? html; @* ViewBag 有 CustomerHelper *@ 如果 MVC 可以很容易地使用相同的“EditorTemplates”和 JS 诱人的 jQuery 模板,我会更喜欢。
猜你喜欢
  • 2013-02-19
  • 1970-01-01
  • 2016-11-23
  • 2011-06-20
  • 2018-05-31
  • 1970-01-01
  • 2012-01-28
  • 2019-07-22
  • 2014-12-29
相关资源
最近更新 更多