【问题标题】:Converting ASP.NET MVC Razor @helper function into a method of a helper class将 ASP.NET MVC Razor @helper 函数转换为辅助类的方法
【发布时间】:2014-11-16 08:08:44
【问题描述】:

考虑以下 ASP.NET MVC razor 视图 sn-p,它定义了一个帮助器

@helper FieldFor<TModel>(Expression<Func<TModel, string>> expression)
{
    <div class="form-group">
        @Html.LabelFor(expression,
                       htmlAttributes:
                           new {@class = "control-label col-md-2"})

        <div class="col-md-10">
            @Html.EditorFor(expression,
                            new
                            {
                                htmlAttributes =
                                new {@class = "form-control"}
                            })
            @Html.ValidationMessageFor(expression, "",
                                       new {@class = "text-danger"})

        </div>
    </div>
}

将其转换为类似于的类的方法的模式是:

public static MvcHtmlString FieldFor(this HtmlHelper helper, FieldFor<TModel>(Expression<Func<TModel, string>> expression))
{
   /* Method */
}

我发现的所有示例都集中在生成不依赖于其他 HTML 帮助程序的标记上。

【问题讨论】:

  • 我认为将其声明为扩展方法是做你想做的事的方式(就像你在上面所做的那样)。那有什么问题?您不希望扩展方法返回标记吗?如果您正在寻找在 Razor 脚本中使用的常规函数​​,您可以使用 @functions 进行编码。这样您就可以声明常规方法,而无需返回标记。我只是不知道您是否可以创建一个外部文件,其中代码声明使用“@functions”在任何地方的 Razor 代码中使用。
  • 没有问题。我正在寻找一种方法来为扩展方法创建 @helper 方法,同时具有完全相同的功能。本质上,我想将这些扩展方法移动到一个类库中,以便在不同的 ASP.NET MVC 应用程序之间重用它们。
  • 看来你已经有了答案。我相信所有要做的就是在 MvcHtmlString 上构建扩展方法并使用 TagBuilder 类来构建标记,而不是直接返回它们。那么你的扩展方法应该返回 new MvcHtmlString(yourTag.toString())。
  • 但是如果不涉及标签,这可能行不通,对吧?

标签: c# asp.net-mvc razor


【解决方案1】:

签名需要是

public static MvcHtmlString FieldFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)

然后你结合使用 TagBuilder 和内置的 html 辅助方法来生成 html

using System;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace YourAssembly.Html
{
  public static class FieldHelper
  {
    public static MvcHtmlString FieldFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
    {
      MvcHtmlString label = LabelExtensions.LabelFor(helper, expression, new { @class = "control-label col-md-2" });
      MvcHtmlString editor = EditorExtensions.EditorFor(helper, expression, new { htmlAttributes = new {@class = "form-control"}})
       MvcHtmlString validation = ValidationExtensions.ValidationMessageFor(helper, expression, null, new { @class = "text-danger" });

       StringBuilder html = new StringBuilder();
       html.Append(editor);
       html.Append(validation);
       TagBuilder innerDiv = new TagBuilder("div");
       innerDiv.AddCssClass("col-md-10");
       innerDiv.InnerHtml = html.ToString();
       html = new StringBuilder();
       html.Append(label);
       html.Append(innerDiv.ToString());
       TagBuilder outerDiv = new TagBuilder("div");
       outerDiv.AddCssClass("form-group");
       outerDiv.InnerHtml = html.ToString();
       return MvcHtmlString.Create(outerDiv.ToString());
    }
  }
}

然后您可以通过将其添加到 web.config 来使其在所有视图中可用

<system.web.webPages.razor>
  <pages pageBaseType="System.Web.Mvc.WebViewPage">
    <namespaces>
      <add namespace="System.Web.Mvc" />
      ....
      <add namespace="YourAssembly.Html" />
    </namespaces>

【讨论】:

  • 该死,我担心这会是我能找到的答案......
【解决方案2】:

这应该很容易。您只需将其编写为HtmlHelper 的扩展方法并使用TagBuilder 来构建您的html:

namespace Sample.Extensions
{
    using System;
    using System.Linq.Expressions;
    using System.Web.Mvc;
    using System.Web.Mvc.Html;

    public static class TestExtensions
    {
        public static MvcHtmlString FieldFor<TModel>(
                                         this HtmlHelper<TModel> helper,
                                         Expression<Func<TModel, string>> expression)
        {
            var mainDiv = new TagBuilder("div");
            mainDiv.AddCssClass("form-group");

            mainDiv.InnerHtml += helper.LabelFor(expression);

            var colDiv = new TagBuilder("div");
            colDiv.AddCssClass("col-md-10");
            colDiv.InnerHtml += helper.EditorFor(expression, 
                                                 new
                                                 {
                                                    htmlAttributes =
                                                        new {@class = "form-control"}
                                                 })
            colDiv.InnerHtml += helper.ValidationMessageFor(
                                        expression, 
                                        "", 
                                        new {@class = "text-danger"});

            mainDiv.InnerHtml += colDiv;

            return new MvcHtmlString(mainDiv.ToString(TagRenderMode.Normal));
        }
    }
}

视图中的用法:

@using Sample.Extensions
@model ...
...
@Html.FieldFor(m => m.MyField)

【讨论】:

  • 您的答案适用于我的解决方案; @stephen 的答案解决了所有属性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 2015-05-30
  • 2021-05-13
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多