避免在 ASP.NET MVC 中重复查看代码

Avoiding Repetitive View Code in ASP.NET MVC

这适用于 Razor 视图中的 ASP.NET MVC 4 应用程序。我正在将模型传递给局部视图,并尝试遍历模型中包含的给定属性列表以显示为 table.

给定类似 List<string> propertyNames 的内容,在此 table 中,我想输出 DisplayNameFor 和 属性 的值,如下所示:

<tr>
    <th>@Html.DisplayNameFor(Model.property)</th>
    <td>@Model.property</td>
</tr>

我必须在部分中执行几次此操作,因为不同的属性对应于部分中不同的 div 元素,其中将插入不同的 table,因此我创建了一个帮手,这就是我挂断电话的地方。首先,我知道如何做到这一点的唯一方法是反射,而且我读到反射很昂贵,尤其是一次只做一个属性。另外,使用这种方法,我无法使 @Html.DisplayNameFor 正常工作,因为使用反射,我不太了解语法:

@helper IterateDetailPropertyNames(List<string> propertyNames) { 
    foreach (var property in propertyNames)
    {
        <tr>
            <th>
                @Html.DisplayNameFor(m => m.GetType().GetProperty(property).GetValue(Model, null));
                @*Error: Templates can be used only with field access, property access...*@
            </th>
            <td>
                @Model.GetType().GetProperty(property).GetValue(Model, null)
            </td>
        </tr>
    }
}

我怎样才能使它工作并改进它?

模型 ModelMetadata 为您提供生成 table 所需的数据。除了 DisplayNameDisplayFormatStringNullDisplayText 等属性之外,它还包含模型值,这些属性是根据应用于您的属性的注释确定的。

有关 ModelMetadata 的更多信息,请参阅 documentation and ASP.NET MVC 2 Templates, Part 2: ModelMetadata

要生成您的 table,您可以编写以下 HtmlHelper 扩展方法

public static class TableHelper
{

    public static MvcHtmlString DisplayTableFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
    {
        // Get the ModelMetadata for the model
        ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
        StringBuilder html = new StringBuilder();
        // Loop through the ModelMetadata of each property in the model
        foreach (ModelMetadata property in metaData.Properties)
        {
            var x = metaData.DisplayFormatString;
            string label = property.DisplayName;
            string value = null;
            if (property.Model == null)
            {
                value = metaData.NullDisplayText;
            }
            else if (metaData.DisplayFormatString != null)
            {
                value = string.Format(metaData.DisplayFormatString, property.Model);
            }
            else
            {
                value = property.Model.ToString();
            }
            TagBuilder labelCell = new TagBuilder("td");
            labelCell.InnerHtml = label;
            TagBuilder valueCell = new TagBuilder("td");
            valueCell.InnerHtml = value;
            StringBuilder innerHtml = new StringBuilder();
            innerHtml.Append(labelCell.ToString());
            innerHtml.Append(valueCell.ToString());
            TagBuilder row = new TagBuilder("tr");
            row.InnerHtml = innerHtml.ToString();
            html.Append(row.ToString());
        }
        TagBuilder table = new TagBuilder("table");
        table.InnerHtml = html.ToString();
        return new MvcHtmlString(table.ToString());
    }
}

并在视图中

@using YourAssembly.TableHelper
....
@Html.DisplayTableFor(m => m)

您还可以将程序集包含在 web.config 文件中,这样视图中就不需要 @using 语句

作为旁注,<table> 元素用于表格数据,不应用于布局。而是考虑使用样式 <div> 元素