【问题标题】:ASP.NET MVC 3 Custom HTML Helpers- Best Practices/UsesASP.NET MVC 3 自定义 HTML 帮助程序 - 最佳实践/使用
【发布时间】:2011-01-26 13:00:22
【问题描述】:

MVC 新手,已通过 asp.net 网站上的教程运行。

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

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

例如,我正在考虑编写一个自定义帮助程序来格式化我需要在不同位置显示的日期,但现在我担心可能会有更优雅的解决方案(即我的模型中的 DataAnnotations)

有什么想法吗?

编辑:

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

【问题讨论】:

  • 我仍然有兴趣看到人们使用自定义 HTML 助手所做的任何其他有趣的事情。随意发布它们!

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


【解决方案1】:

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

  • Html.BodyId():为视图添加自定义 css 时生成一个常规的 body id 标签供参考。
  • Html.SubmitButton(string):生成 input[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 可以提供您需要的所有自定义,它可以工作 grrrrrrrreat!

故事的寓意——HtmlHelpers 可以使您免受全球设计变化的影响,这些变化会在一个又一个视图中破坏手工制作的标记。我喜欢他们。但是你可能会过火,有时部分视图比编码的助手更好。 我用来决定辅助视图还是部分视图的一般经验法则:如果 HTML 块需要大量条件逻辑或编码技巧,我会使用辅助函数(将代码放在代码应该在的位置);如果不是,如果我只是输出普通标记而没有太多逻辑,我会使用局部视图(将标记放在应该标记的位置)。

希望这能给你一些想法!

【讨论】:

  • 好帖子!如果你不介意的话,我肯定会从这里复制/粘贴一些;)
  • 很好的答案。我花了一点时间才弄清楚我需要使用 System.Web.Mvc.Html;让 .EditorFor 扩展显示出来
【解决方案2】:

在格式化DisplayFormat 属性的情况下可能是一个不错的解决方案:

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

然后简单地说:

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

就截断字符串而言,自定义 HTML 助手是一个很好的解决方案。


更新:

关于您的 EDIT,自定义 HTML 助手可能在这种情况下工作,但还有一种我非常喜欢的替代方法:视图模型。因此,如果在这个特定视图中您总是要显示名称的串联,那么您可以定义一个视图模型:

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

现在控制器将查询存储库以获取模型,然后将此模型映射到将传递给视图的视图模型,以便视图可以简单地@Html.DisplayFor(x =&gt; x.FullName)。模型和视图模型之间的映射可以通过 AutoMapper 之类的框架来简化。

【讨论】:

  • 非常有趣。几乎似乎自定义 html 助手是最后的手段。
【解决方案3】:
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);
}

【讨论】:

  • 不要只发布代码答案。它可能对 op 有用,但对未来的读者没有用。我建议你应该添加一些解释你的解决方案是如何工作的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-14
  • 2014-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多