2012-06-29 174 views
27

對於ViewBag,我聽說這是一個不可以使用。 我會假設從ViewBag的內容應該被納入視圖模型?MVC ViewBag最佳實踐

問:

  1. 是我的假設之上的最佳實踐。 (不使用ViewBag,其次使用視圖模型)

  2. 是否有ViewBag絕對必要的情況?

+7

從微軟的角度來說,我們不同意從不使用ViewBag或ViewBag是沒有用號到ViewBag傳遞模型數據又是另一回事,應該氣餒。使用ViewBag傳遞元數據(選擇列表)很好。由桑德森和其他書籍的Pro MVC使用它們,並沒有做出這樣的明確宣言 - 2.必要的絕對 - 我懷疑它。 – RickAndMSFT

回答

25

ViewBag是一個動態字典。因此,當使用ViewBag在動作方法和視圖之間傳輸數據時,如果在嘗試訪問視圖中的ViewBag項目時在代碼中輸入錯誤,則編譯器將無法捕捉。您的視圖將在運行時崩潰:(

通常,使用視圖模型在您的操作方法和視圖之間傳輸數據是一個好主意view model是一個簡單的POCO類,它具有特定於視圖的屬性。如果你想傳遞一些額外的數據來查看,添加一個新的屬性到你的視圖模型,並使用它。強大的類型視圖使代碼更清潔,更容易維護。使用這種方法,你不需要做顯式的轉換您viewbag字典項某些類型來回,你有看法袋做。

public class ProductsForCategoryVm 
{ 
    public string CategoryName { set;get; } 
    public List<ProductVm> Products { set;get;}  
} 
public class ProductVm 
{ 
    public int Id {set;get;} 
    public string Name { set;get;} 
} 

而在你的操作方法,創建這個視圖模型的對象,加載性能,發送到視圖。

public ActionResult Category(int id) 
{ 
    var vm= new ProductsForCategoryVm(); 
    vm.CategoryName = "Books"; 
    vm.Products= new List<ProductVm> { 
    new ProductVm { Id=1, Name="The Pragmatic Programmer" }, 
    new ProductVm { Id=2, Name="Clean Code" } 
    } 
    return View(vm); 
} 

而且你的觀點,這是強類型的視圖模型,

@model ProductsForCategoryVm 
<h2>@Model.CategoryName</h2> 
@foreach(var item in Model.Products) 
{ 
    <p>@item.Name</p> 
} 

下拉數據?

很多教程/書籍都有使用ViewBag作爲下拉數據的代碼示例。我個人仍然覺得ViewBag不應該用於這個。它應該是您的視圖模型中的List<SelectListItem>類型的屬性,以傳遞下拉數據。這裏是一個post與示例代碼如何做到這一點。

是否有ViewBag絕對必要的情況?

有一些有效的使用情況下,您可以(不需要)使用ViewBag發送數據。例如,您想要在佈局頁面上顯示某些內容,則可以使用ViewBag。另一個示例是默認MVC模板中存在的ViewBag.Title(用於頁面標題)。

public ActionResult Create() 
{ 
    ViewBag.AnnouncementForEditors="Be careful"; 
    return View(); 
} 

而且在佈局,可以用ViewBags閱讀ViewBag.AnnouncementForEditors

<body> 
<h1>@ViewBag.AnnouncementForEditors</h1> 
<div class="container body-content"> 
    @RenderBody() 
</div> 
</body> 
+0

模型存儲在ViewBag中,所以它始終是必需的。使用魔術字符串可能不是可維護性的高峯,但除了使用模型所做的所有操作之外,都強制聲明類型和頁面變量的約定。 –

0
  1. 號使用ViewModels
  2. 不。如果你設計了一個完美的ViewModel,你永遠不需要ViewBag。
4

1)我的假設高於最佳實踐。 (不使用ViewBag和 秒使其在視圖模型中)

是的。

2)是否有ViewBag絕對必要的情況?

不是。您存儲在ViewBag中的所有內容都可以進入傳遞給視圖的視圖模型。

+0

元數據呢?我們應該從模板中抽出@ ViewBag.Title嗎? – RickAndMSFT

+7

Yeap,把它扔掉。請。我不想在ASP.NET MVC 4中看到它。它讓我想吐。如果您將其標記爲「內部」,那麼在框架內部使用它,這樣開發人員就不必面對它。 –

4

的問題和建議的最佳實踐歸結編譯時間檢查。 ViewBag只是​​字典,因此你會得到'神奇'的字符串,所以如果你最終改變了其中一個viewbag項目的對象類型或者直到運行時纔會知道的鍵名,即使你使用<MvcBuildViews>true</MvcBuildViews>預編譯視圖。

堅持查看模型是最好的,即使您必須一次又一次地修改它們以適合特定視圖。

26

1)我的假設是否超出最佳實踐。 (不使用ViewBag和 第二要有它在視圖模型)

你應該通過ViewBag使用的ViewModels,而不是通過數據儘可能地。

2)是否有ViewBag絕對必要的情況?

在任何情況下ViewBag都是絕對必要的。但是,我個人更喜歡使用ViewBag而不是View Model的一些數據。例如,當我需要填充預定義值(例如城市)的下拉框時,我使用ViewBag來攜帶SelectListItem數組來查看。我不想用這些數據來污染我的ViewModels。

+4

符合我們(MS)公佈的指導的出色響應。我只會將其從傳遞數據更改爲傳遞模型數據(元數據除外)請參閱我的教程的底部http://www.asp.net/mvc/tutorials/javascript/working-with-the-dropdownlist-box-and -jquery/examining-how-aspnet-mvc-scaffolds-the-dropdownlist-helper – RickAndMSFT

+0

@RickAndMSFT,我必須管理當我第一次學習ViewBags時,我利用了你的帖子。好的文章。 – SadullahCeran

+1

好的答案,我也認爲使用ViewBag而不是污染視圖模型和一系列要傳遞給視圖的選項是一種很好的做法。 如果列表在ViewModel中傳遞,這是因爲列表可能會被編輯,或者因爲它對模型「有意義」。但是對於只有一個選項的選項列表來說,ViewBag看起來更清晰。 – iberodev

2

我發現了ViewBag的一些用法,其中所有頁面都具有通用功能,並且功能不依賴於顯示的頁面。例如,假設你正在構建StackOverflow。工作板顯示在每個頁面上,但顯示的工作與頁面無關(我的用法在概念上相似)。將屬性添加到每個ViewModel將會很困難並且耗時,並且會對您的測試帶來不便。在這種情況下,我認爲這不值得。

我已經使用了交叉切割數據的基礎ViewModel類,但是如果你多於一個(例如作業&堆棧交換站點列表),你必須開始填充額外的數據,或者其他一些濫用一個ViewModel,再加上你需要一個ViewModel構建器來填充基礎數據。

至於魔線問題,有很多解決方案。常量,擴展方法等。

說了這麼多,如果你的頁面上顯示的東西取決於頁面的上下文,ViewModel就是你的朋友。

埃裏克

+0

我知道這是舊的,但它不會更好地使用部分作業列表和@ {Html.RenderAction(「SomeAction」,「SomeController」);}從視圖? – wingyip

1

如果您不能重新設計現有視圖模型使用ViewBag。

0

2.Are存在的情況下一個ViewBag是絕對必要的?

在某些情況下,您需要在佈局,視圖和局部視圖之間共享Controller中的數據。在這種情況下,ViewBag非常有幫助,我懷疑有更好的方法。

0

如果沒有用例,它將不會被首先實現。是的,你可以用ViewModels做所有的事情,但是如果你不需要一個呢?其中一種情況是編輯實體。您可以直接將DTO作爲模型傳遞。

@model CategoryDto 
<div class="md-form form-sm"> 
    <input asp-for="Name" class="form-control"> 
    <label asp-for="Name">("Category Name")</label> 
</div> 

但是,如果你想選擇類別父?實體DTO理想地只擁有它自己的值,因此填充選擇列表您使用ViewBag

<select asp-for="ParentId" asp-items="ViewBag.ParentList"> 
    <option value="">None</option> 
</select> 

爲什麼這樣做?那麼如果你有50種類型的實體,每種實體都有不同的值的選擇,你可以避免創建50個額外的ViewModels。