ASP.NET MVC 3自定义HTML助手-最佳实践/用途

33

刚接触MVC,一直在asp.net网站上的教程中学习。

其中包括一个自定义HTML助手的示例,用于截断显示在表格中的长文本。

想知道其他人使用HTML助手时想出了哪些解决方案,并且在创建/使用它们时是否有任何最佳实践或需要避免的事情。

例如,我正在考虑编写一个自定义助手来格式化日期以便在各种地方显示,但现在担心可能有更优雅的解决方案(即我的模型中的数据注释)。

你们有什么想法吗?

编辑:

我刚想到另一个潜在的用途......字符串连接。

自定义助手可以将用户ID作为输入并返回用户的全名...

结果可能是某种形式的(Title)(First)(Middle)(Last),具体取决于这些字段中哪些可用。只是一个想法,我还没有尝试过类似的东西。


1
我仍然对查看其他人使用自定义HTML助手完成的任何有趣的事情感兴趣。欢迎随时发布它们! - stephen776
3个回答

101
我经常使用HtmlHelpers,最常见的是封装HTML样板生成,以防我改变主意。 我有一些这样的帮助程序:
  • Html.BodyId():生成传统的body id标记,用于在视图中添加自定义css时进行引用。
  • Html.SubmitButton(string):生成input[type=submit]或button[type=submit]元素,具体取决于我想如何设置按钮样式。
  • Html.Pager(IPagedList):用于从分页列表模型生成分页控件。
  • 等等....
我的一个最喜欢的HtmlHelpers用途是DRY(不要重复自己)常见的表单标记。 通常,我有一个包含表单行的容器div,一个用于标签的div,以及一个用于输入,验证消息,提示文本等的标签。 最终,这可能会成为大量的样板HTML标记。 下面是我处理此问题的示例:
public static MvcHtmlString FormLineDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string labelText = null, string customHelpText = null, object htmlAttributes = null)
{
    return FormLine(
        helper.LabelFor(expression, labelText).ToString() +
        helper.HelpTextFor(expression, customHelpText),
        helper.DropDownListFor(expression, selectList, htmlAttributes).ToString() +
        helper.ValidationMessageFor(expression));
}

public static MvcHtmlString FormLineEditorFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string templateName = null, string labelText = null, string customHelpText = null, object htmlAttributes = null)
{
    return FormLine(
        helper.LabelFor(expression, labelText).ToString() +
        helper.HelpTextFor(expression, customHelpText),
        helper.EditorFor(expression, templateName, htmlAttributes).ToString() +
        helper.ValidationMessageFor(expression));
}

private static MvcHtmlString FormLine(string labelContent, string fieldContent, object htmlAttributes = null)
{
    var editorLabel = new TagBuilder("div");
    editorLabel.AddCssClass("editor-label");
    editorLabel.InnerHtml += labelContent;

    var editorField = new TagBuilder("div");
    editorField.AddCssClass("editor-field");
    editorField.InnerHtml += fieldContent;

    var container = new TagBuilder("div");
    if (htmlAttributes != null)
        container.MergeAttributes(new RouteValueDictionary(htmlAttributes));
    container.AddCssClass("form-line");
    container.InnerHtml += editorLabel;
    container.InnerHtml += editorField;

    return MvcHtmlString.Create(container.ToString());
}

public static MvcHtmlString HelpTextFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string customText = null)
{
    // Can do all sorts of things here -- eg: reflect over attributes and add hints, etc...
}    

一旦您完成了这个步骤,您就可以像这样输出表单行:
<%: Html.FormLineEditorFor(model => model.Property1) %>
<%: Html.FormLineEditorFor(model => model.Property2) %>
<%: Html.FormLineEditorFor(model => model.Property3) %>

当你使用HtmlHelpers时,只需添加属性到你的模型中,就可以在页面上显示所有标签、输入框、提示和验证信息。你可以反射这些属性,让你的代码更加智能和DRY。当然,如果你不能在表单设计上达成标准化,这将是一种浪费时间的做法。但是,在简单情况下,如果css可以提供你所需的所有自定义内容,那么它的效果会非常好!

故事的寓意是-- HtmlHelpers可以使你免受全局设计变化破坏手工标记的影响。我喜欢他们。但是你可能会过度使用,有时候部分视图比编码帮助器更好。我用于决定使用帮助器还是部分视图的一个通用原则是:如果HTML块需要大量的条件逻辑或编码技巧,我使用帮助器(把代码放在应该放置代码的地方);否则,如果我只是输出没有太多逻辑的公共标记,我使用部分视图(把标记放在应该放置标记的地方)。

希望这给你一些启示!


3
很棒的文章!如果你不介意,我会从这里复制/粘贴一些内容 ;) - Yngve B-Nilsen
7
好的回答。不过我花了一点时间才弄清楚我需要使用System.Web.Mvc.Html;才能让.EditorFor扩展显示出来。 - Nick

16

如果需要格式化数据,DisplayFormat 属性可能是一个不错的解决方案:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")]
public DateTime Date { get; set; }

然后简单地执行:

@Html.DisplayFor(x => x.Date)

就截取字符串而言,自定义HTML助手是一个不错的解决方案。


更新:

关于你的编辑,自定义HTML助手可能适用于这种情况,但还有一种我非常喜欢的替代方法:视图模型。因此,如果在这个特定的视图中,您总是要显示名称的连接,则可以定义一个视图模型:

public class PersonViewModel
{
    public string FullName { get; set; }
}

现在,控制器将查询存储库以获取模型,然后将该模型映射到一个视图模型,该视图模型将传递给视图,以便视图可以简单地使用@Html.DisplayFor(x => x.FullName)。使用像AutoMapper这样的框架可以简化模型和视图模型之间的映射。


4
非常有趣。几乎看起来像自定义HTML帮助器是最后的手段。 - stephen776

0
public static HtmlString OwnControlName<T, U>(this HtmlHelper<T> helper, Expression<Func<T, U>> expression, string label_Name = "", string label_Title = "", Attr attr = null)
        {
            TemplateBuilder tb = null;
            string template = null;
          if (expression == null) throw new ArgumentException("expression");
 obj = helper.ViewData.Model;
                tb.Build(obj, expression.Body as MemberExpression, typeof(T), new SimpleTemplate(new TextArea()), label_Name, label_Title, attr);
                template = tb.Get();
 return new MvcHtmlString(template);
}

不要只发布代码答案。这对提问者可能有用,但对未来的读者没有帮助。我建议您应该添加一些解释,说明您的解决方案如何工作。 - Parth Pandya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接