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

时间:2011-01-26 13:00:22

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

MVC的新手,并且已经在asp.net网站上运行了这些教程。

它们包含一个自定义html帮助器示例,用于截断表中显示的长文本。

只是想知道人们使用HTML帮助程序提出了哪些其他解决方案,以及在创建/使用它们时是否有任何最佳实践或要避免的事项。

作为一个例子,我正在考虑编写一个自定义助手来格式化我需要在各个地方显示的日期,但我现在担心可能有一个更优雅的解决方案(我的模型中的I.E.DataAnnotations)

有什么想法吗?

修改

我刚想到的另一个潜在用途......字符串连接。 自定义帮助程序可以将userID作为输入并返回用户全名... 结果可能是(标题)(第一)(中)(最后)的某种形式,具体取决于哪些字段可用。只是一个想法,我还没有尝试过这样的事情。

3 个答案:

答案 0 :(得分:100)

我一直使用HtmlHelpers,最常见的是封装样板HTML的生成,以防我改变主意。我有这样的帮手:

  • Html.BodyId():在为视图添加自定义css时生成传统的body id标记以供引用。
  • Html.SubmitButton(string):生成输入[type = submit]或button [type = submit]元素,具体取决于我想如何设置按钮的样式。
  • Html.Pager(IPagedList):用于从分页列表模型生成分页控件。
  • 等....

我最喜欢的HtmlHelpers之一就是干掉常见的表单标记。通常,我有一个用于表单行的容器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) %>

...和BAM,您的所有标签,输入,提示和验证消息都在您的页面上。同样,您可以在模型上使用属性并反映它们以获得真正的智能和干燥。当然,如果你不能标准化你的表单设计,这将浪费时间。但是,对于简单的情况,css可以提供您需要的所有自定义,它可以运行grrrrrrrrrreat!

故事的道德 - HtmlHelpers可以使您免受全局设计变更的影响,在视图后查看手工制作的标记。我喜欢他们。但是你可以过火,有时局部视图比编码助手更好。 我用来决定辅助视图和部分视图之间的一般经验法则:如果HTML的大块需要大量的条件逻辑或编码技巧,我会使用帮助程序(将代码应放在代码中);如果没有,如果我只是在没有太多逻辑的情况下输出公共标记,我使用局部视图(将标记放在标记应该是的位置)。

希望这会给你一些想法!

答案 1 :(得分: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等框架进行简化。

答案 2 :(得分: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);
}