2012-06-29 96 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? (感謝您的時間順便說一句,只是想得到底部的東西) –