ASP。NET MVC 3 -部分vs显示模板vs编辑器模板

所以,标题应该不言自明。

在ASP中创建可重用的组件。NET MVC,我们有3个选项(可能是其他我没有提到的):

局部视图:

@Html.Partial(Model.Foo, "SomePartial")

定制编辑器模板:

@Html.EditorFor(model => model.Foo)

自定义显示模板:

@Html.DisplayFor(model => model.Foo)

就实际的View/HTML而言,所有三种实现都是相同的:

@model WebApplications.Models.FooObject


<!-- Bunch of HTML -->

所以,我的问题是——何时/如何决定使用三种方法中的哪一种?

我真正想要的是在创建一个之前问自己的问题列表,答案可以用来决定使用哪个模板。

以下是我发现EditorFor/DisplayFor更好的2件事:

  1. 它们在呈现HTML helper时尊重模型层次结构(例如,如果你的“Foo”模型上有一个“Bar”对象,“Bar”的HTML元素将使用“Foo.Bar”来呈现。ElementName”,而一个部分将有“ElementName”)。

  2. 更健壮,例如,如果你在ViewModel中有某个东西的List<T>,你可以使用@Html.DisplayFor(model => model.CollectionOfFoo), MVC足够聪明,可以看到它是一个集合,并为每个项目呈现单个显示(与Partial相反,这将需要显式的for循环)。

我也听说过DisplayFor呈现一个“只读”模板,但我不明白-我不能扔一个表单在那里吗?

有人能告诉我其他原因吗?有没有比较这三个的列表/文章?

69780 次浏览

EditorFor vs DisplayFor很简单。这些方法的语义是分别生成编辑/插入视图和显示/只读视图。在显示数据时使用DisplayFor(即当你生成包含模型值的div和span时)。在编辑/插入数据时使用EditorFor(即在表单中生成输入标记时)。

上述方法是以模型为中心的。这意味着他们将考虑模型元数据(例如,你可以用[UIHintAttribute][DisplayAttribute]注释你的模型类,这将影响选择哪个模板来生成模型的UI。它们通常也用于数据模型(即表示数据库中行等的模型)

另一方面,Partial是以视图为中心的,因为你主要关心的是选择正确的局部视图。视图不需要模型来正确地运行。它可以只有一组通用的标记,可以在整个站点中重用。当然,很多时候你想要影响这个部分的行为在这种情况下,你可能想要传入一个适当的视图模型。

你没有问@Html.Action,它也值得在这里提到。你可以认为它是Partial的一个更强大的版本,因为它执行一个控制器子动作,然后呈现一个视图(通常是一个局部视图)。这很重要,因为子操作可以执行不属于局部视图的附加业务逻辑。例如,它可以表示一个购物车组件。使用它的原因是避免在应用程序中的每个控制器中执行与购物车相关的工作。

最终,选择取决于您在应用程序中建模的是什么。还要记住,你可以混合搭配。例如,你可以有一个局部视图调用EditorFor helper。这实际上取决于您的应用程序是什么,以及如何分解它以鼓励最大限度地重用代码,同时避免重复。

你当然可以可以自定义DisplayFor来显示可编辑的表单。但是惯例是DisplayForreadonly,而EditorFor是用于编辑的。坚持约定将确保无论你向DisplayFor传递什么,它都会做相同类型的事情。

为了给我2c的价值,我们的项目使用了一个带有几个jQuery选项卡的部分视图,每个选项卡都用自己的部分视图渲染它的字段。这一直很好,直到我们添加了一个特性,其中一些选项卡共享一些公共字段。我们的第一个方法是使用这些公共字段创建另一个局部视图,但是当使用EditorFor和DropDownListFor渲染字段和下拉列表时,这变得非常笨拙。为了获得唯一的id和名称,我们必须根据呈现它的父部分视图来呈现字段的前缀:

    <div id="div-@(idPrefix)2" class="toHide-@(idPrefix)" style="display:none">
<fieldset>
<label for="@(idPrefix).Frequency">Frequency<span style="color: #660000;"> *</span></label>


<input name="@(idPrefix).Frequency"
id="@(idPrefix)_Frequency"
style="width: 50%;"
type="text"
value="@(defaultTimePoint.Frequency)"
data-bind="value: viewState.@(viewStatePrefix).RecurringTimepoints.Frequency"
data-val="true"
data-val-required="The Frequency field is required."
data-val-number="The field Frequency must be a number."
data-val-range-min="1"
data-val-range-max="24"
data-val-range="The field Frequency must be between 1 and 24."
data-val-ignore="true"/>


@Html.ValidationMessage(idPrefix + ".Frequency")


... etc


</fieldset>
</div>

这变得非常丑陋,所以我们决定使用编辑器模板,这工作得更干净。我们添加了一个带有公共字段的新视图模型,添加了一个匹配的编辑器模板,并使用来自不同父视图的编辑器模板渲染字段。编辑器模板正确地呈现id和名称。

因此,简而言之,我们使用编辑器模板的一个令人信服的理由是需要在多个选项卡中呈现一些公共字段。部分视图不是为此而设计的,但编辑器模板完美地处理了这种情况。

使用_partial视图方法,如果:

  1. 视图中心逻辑
  2. 在这个视图中只保留所有_partial视图相关的HTML。在模板方法中,你必须在模板视图之外保留一些HTML,如“Main Header或任何外部边框/设置”。
  3. 想要使用URL.Action("action","controller")渲染带有逻辑(来自控制器)的部分视图。

使用Template的原因:

  1. 要删除ForEach(Iterator)。Template可以很好地将Model标识为列表类型。它会自动完成的。
  2. 模型中心逻辑。如果在同一个displayfortemplate文件夹中发现了多个视图,那么渲染将依赖于传递的模型。
到目前为止还没有提到的另一个区别是,partialview不添加模型前缀,而模板可以 在这里是问题