2012-06-29 70 views
62

我听说在视图中有@foreach是一个禁忌。意思是,这个观点不应该有任何逻辑。 @foreach的逻辑应该放在哪里的最佳实践是什么?MVC Razor @foreach

@foreach.. 
+2

你在哪里读过的?逻辑是剃刀的意思! –

+3

请阅读以下ms教程http://www.asp.net/web-pages/tutorials/basics/2-introduction-to-asp-net-web-programming-using-the-razor-syntax –

回答

130

什么是其中用于@foreach的逻辑应该是最好的做法?

无处不在,只是摆脱它。你可以使用编辑器或显示模板。

因此,例如:

@foreach (var item in Model.Foos) 
{ 
    <div>@item.Bar</div> 
} 

完全可以通过精细的显示模板替换:

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

,然后你会定义相应的显示模板(如果你不喜欢default one )。所以,你会定义一个可重复使用的模板~/Views/Shared/DisplayTemplates/Foo.cshtml它会自动通过框架的FOOS集合中的每个元素被渲染(IEnumerable<Foo> Foos { get; set; }):

@model Foo 
<div>@Model.Bar</div> 

显然完全相同的约定申请应在情况下使用编辑模板,你想要显示一些输入字段,允许您编辑视图模型,而不是只显示为只读模式。

+0

我同意@DarinDimitrov说,第二个例子看起来和读得更好。虽然我没有看到显示内的foreach循环的问题! –

+0

@NicholasKing,为编辑器模板的输入字段生成专有名称时出现问题。例如,看下面的[Noobsyke的答案](http://stackoverflow.com/a/11261698/29407)。将其DisplayFor替换为EditorFor,并且模型联编程序将不起作用,因为他没有遵守惯例。 –

+2

@DarinDimitrov多数民众赞成在真正的,如果它是一个严格的MVC模型,你正在编码,但如果出现一种情况下集合需要循环,这不是在模型中,我没有看到使用foreach –

11

我使用@foreach当我发送包含的实体的列表,如果我送为模型实体的Foo包含Foo1(List<Foo1>)(例如,以显示在1个视图2个栅极)

例如一个实体和Foo2(List<Foo2>)

可以参考我的第一清单具有:

@foreach (var item in Model.Foo.Foo1) 
{ 
    @Html.DisplayFor(modelItem=> item.fooName) 
} 
74

当人们说不要放在观点的逻辑,他们通常指的是业务逻辑,而不是渲染逻辑。根据我的观点,我认为在视图中使用@foreach非常好。

+15

同意。让我想起旧的语义HTML辩论,最终导致人们尝试使用div和CSS为实际表格数据创建“表”,因为它们如此反表。 –

+1

我同意。人类在错误的方向上很糟糕。我是否真的需要一个新的文件夹和一个新的视图,只是为了在viewmodel的列表中显示一些东西? – mmcrae

+0

创建响应视图是否需要使用div/css创建表格数据视图? – frostshoxx

6

对@DarinDimitrov的回复,用于在剃刀视图中使用foreach的情况。使用过载指示模板@Html.DisplayFor(x => x.Foos, "YourTemplateName)

<li><label for="category">Category</label> 
     <select id="category"> 
      <option value="0">All</option> 
      @foreach(Category c in Model.Categories) 
      { 
       <option title="@c.Description" value="@c.CategoryID">@c.Name</option> 
      } 
     </select> 
</li> 
+6

哇的人,你会在视图中写这样的东西?为什么不写一个可重用的定制助手àla Html.DropDownListFor',它只会考虑标题?这是微不足道的,不会把你的意见变成意大利面代码:http://stackoverflow.com/a/7938038/29407 –

+7

@DarinDimitrov是的,我们在一个非常敏捷的环境中工作,这意味着像这样的场景有时会阻止我们使用像DropDownFor,因为我们并不总是有一个明确的要求。我相信在这种情况下,下拉最初并不需要“全部”,然后它只能在视图上的一个DropDown中进行。由于此页面使用ajax更新其不是严格的MVC模式,并且您不能根据要求将产品上传到所有类别。不理想,但有时不可避免。 –

+0

也许一个更好的例子会使用这个来在选择列表中呈现'optgroup'元素,因为在HtmlHelpers中不支持这个元素。如果你只需要添加一个项目到选择列表,有更好的方法来实现,然后仍然使用助手。 –

2

The answer将无法​​正常工作。

似乎是这样设计的,see this case。也异常的框架给了(约并未如预期的类型)是相当误导和愚弄我第一次尝试(感谢@CodeCaster)

在这种情况下你必须使用@foreach

@foreach (var item in Model.Foos) 
{ 
    @Html.DisplayFor(x => item, "FooTemplate") 
} 
+0

这个答案是由MVC上的人编写的,所以我猜他们知道他们在说什么。 MVC将迭代'IEnumerable '并为每个元素调用类型为'T'的模板。 – CodeCaster

+0

关于您的编辑:无论是您的代码是错误的还是特定MVC版本中的错误(在5.2.2中适用于我)。它应该按照接受的答案中的描述工作。如果你愿意的话,不要说它是错的,而应该打开你自己的问题。 – CodeCaster

+0

@CodeCaster我相信我的回答为这个特定案例增加了一些头脑(这浪费了我一些时间来弄清楚什么地方出了问题)。请你补充一些解释,以保持downvote? (感谢您的时间顺便说一句,只是想得到底部的东西) –