我是否需要在DisplayFor / EditorFor中使用该模型进行数据访问?

时间:2012-04-27 18:39:40

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

传递给DisplayForEditorFor的表达式何时需要使用该模型进行数据访问?

例如,我可能有以下模型

class MyModel {
   IList<SubModel> Subs { get; set; }
}
class SubModel {
   string Name { get; set; }
}

然后我可以使用从模型开始的完整路径编写视图数据访问:

@Html.DisplayFor(m => m.Subs[i].Name)

或者,我可能在视图中没有使用该模型:

@foreach (var item in Model.Subs) {
    @Html.DisplayFor(m => item.Name)
}

但在上面我并没有真正使用该模型。这似乎每次我尝试都有效,但在什么条件下我可能遇到问题?

EditorFor通常使用Expression在表单元素中构建名称/ ID。在指定传递给EditorFor的表达式时不使用模型是否安全?

1 个答案:

答案 0 :(得分:1)

简短答案是肯定的 - 必须有一个模型作为参数传递给lambda方法。如果您的View没有模型并且您调用DisplayFor或EditorFor,您将看到错误消息“模板只能用于字段访问,属性访问,单维数组索引或单参数自定义索引器表达式。”

因此,您必须拥有一个模型才能使用DisplayFor,但实际上您不必使用它。例如,您可以这样做:

Html.EditorFor(m => i)

在这种情况下,Html名称和ID都将是“i”。

但是需要注意一些注意事项。例如,您可能希望在“共享/显示模板”或“编辑模板”文件夹中为SubModel创建强类型的局部视图。在这种情况下,您可以使用带有DisplayFor的foreach。

如果您使用的是EditorFor,并且希望发布的字段绑定回模型,则需要使用:

for (i = 0; ...)

而不是foreach,以便您的Html表单字段以可绑定的名称结束,例如Subs [1] .Name。如果您使用foreach,则所有输入都将具有相同的名称和ID,例如:

id="s_Name" name="s.Name" 

而使用for循环,你得到:

id="SubModels_0__Name" name="SubModels[0].Name"

for循环生成合法的html(唯一ID),可以反弹到服务器上的列表。

澄清一下:当您使用EditorFor或DisplayFor时,有两件事需要注意。首先,传入的表达式确定用于Html元素的字段名称。如果表达式与您的模型相关,则名称派生自模型,如上例所示。所以,如果我绑定到模型的子类:

Html.DisplayFor(m => m.Submodel.Name)

Html字段名称将为“Submodel.Name”,它将在回发时重新绑定到同一层次结构(请注意,您也可以使用其中一个重载方法自行设置名称)。

第二个方面是您的表达式是键入的(即,它解析为CLR类型或您的一个自定义类型)。为了呈现该类型,MVC查找模型匹配的模板。它使用从当前View文件夹开始的路径层次结构查找其模板,然后查找共享文件夹,如果找不到自定义文件夹,则会回退到其内部模板。

所以你需要考虑这两个来实现你想要的渲染和回发绑定。但是,如果您只对显示数据感兴趣,则不必担心与您的模型匹配的Html字段名称,您可以使用任意名称或根本不使用任何名称,让MVC生成它们。但是你也应该知道Html ID应该是唯一的,就像上面的foreach例子一样,你可以得到相同的id。目前的浏览器似乎没有问题,但如果你想使用Javascript来选择ID,那将会很有趣。