MVC3中 ViewBag、ViewData和TempData的使用和區別



在MVC3開始,視圖數據可以通過ViewBag屬性訪問,在MVC2中則是使用ViewData。MVC3中保留了ViewData的使用。ViewBag 是動態類型(dynamic),ViewData 是一個字典型的(Dictionary)。
它們的定義如下:

public dynamic ViewBag { get; }
public ViewDataDictionary ViewData { get; set; }

控制器中代碼:

public ActionResult Index()
{
ViewBag.Message_ViewBag = "I am viewbag";
ViewData["Message_ViewData"] = "I am viewdata";

return View();
}

 

視圖代碼:

@{
ViewBag.Title = "主頁";
}

<h2>@ViewBag.Message_ViewBag</h2>
<h2>@ViewData["Message_ViewData"]</h2>

 

運行圖:

當然我們可以在視圖里面這樣寫:

<h2>@ViewBag. Message_ViewData </h2>
<h2>@ViewData["Message_ViewBag "]</h2>

運行結果是一樣的,這里表示它們倆是互通的。

ViewBag和ViewData的區別:
ViewBag 不再是字典的鍵值對結構,而是 dynamic 動態類型,它會在程序運行的時候動態解析。
使用ViewBag
控制器代碼:

public ActionResult Index()
{
string[] items = new string[] {"one","two","three" };
ViewBag.Items = items;// viewbag是一個新的dynamic關鍵字的封裝器 //ViewData["Items"] = items;
return View();
}

 


視圖代碼:

<ul>
@foreach (dynamic p in ViewBag.Items)
{ 
<li>The item is: @p</li>
}
</ul>

其中dynamic p可以用var p或者string p取代
執行效果:

如果使用ViewData,則會出現如下錯誤:

這時如果我們希望使用ViewData,就需要我們自己手動去將它強制轉換為數組。通過調試,我們可以看到

string[] items = new string[] { "one", "two", "three" };
ViewBag.Items = items;
ViewData["Items"] = items;

賦值后的ViewBag和ViewData都是字符串數組形式。如下圖:

只是ViewData為object型,而ViewBag為dynamic型。而dynamic型與object型的區別則是在使用時它會自動根據數據類型轉換,而object型則需要我們自己去強制轉換。比如上面我們遍歷ViewBag.Items時,它自動根據數據類型轉換,而ViewData則需要我們強制轉換,如下:

@foreach (string a in (string[])ViewData["Items"])
{
<li>The item is: @a</li>
}

 

此外,通過轉到定義我們可以看到:

[Dynamic]
public dynamic ViewBag { get; }
public ViewDataDictionary ViewData { get; set; }

這里ViewBag只有get方法,沒有set方法,但是我們在上面卻給ViewBag賦值了。通過
反編譯發現ViewBag代碼如下:

[Dynamic]
public object ViewBag
{
[return: Dynamic]
get
{
Func<ViewDataDictionary> viewDataThunk = null;
if (this._dynamicViewDataDictionary == null)
{
if (viewDataThunk == null)
{
viewDataThunk = () => this.ViewData;
}
this._dynamicViewDataDictionary = new DynamicViewDataDictionary(viewDataThunk);
}
return this._dynamicViewDataDictionary;
}
}

 

不難看出ViewBag返回的是_dynamicViewDataDictionary,繼續跟蹤發現_dynamicViewDataDictionary屬於 DynamicViewDataDictionary類,其代碼如下:

internal sealed class DynamicViewDataDictionary : DynamicObject
{
// Fields
private readonly Func<ViewDataDictionary> _viewDataThunk;

// Methods
public DynamicViewDataDictionary(Func<ViewDataDictionary> viewDataThunk);
public override IEnumerable<string> GetDynamicMemberNames();
public override bool TryGetMember(GetMemberBinder binder, out object result);
public override bool TrySetMember(SetMemberBinder binder, object value);

// Properties
private ViewDataDictionary ViewData { get; }
}
其中有TryGetMember和TrySetMember方法,點開這兩個方法:
public override bool TrySetMember(SetMemberBinder binder, object value)
{
this.ViewData[binder.Name] = value;
return true;
}

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = this.ViewData[binder.Name];
return true;
}

 

發現ViewBag其實本質就是ViewData,只是多了層Dynamic控制。所以,使用何種方式完全取決於你個人的愛好。

TempData的使用
同ViewData和ViewBag一樣,TempData也可以用來向視圖傳遞數據。只是ViewData和ViewBag的生命周期和View相同,只對當前View有用。而TempData則可以在不同的Action中進行傳值,類似webform里的Seesion。如下:

public ActionResult Index()
{
ViewBag.hello = "hello,this is viewBag";
ViewData["hi"] = "hi,this is viewData";
TempData["abc"] = "this is tempdata";
return View();
}

然后在About視圖里面調用:

<h2>關於</h2>
<p>
@ViewBag.hello
@ViewData["key"]
@TempData["abc"]
</p>

頁面效果如下:

這里只獲取到了TempData["abc"]的值,但是TempData的值在取了一次后則會自動刪除,這時我再刷新頁面,則TempData["abc"]為Null了。通過反編譯查看代碼,發現TempData數據在調用后則會自動刪除。詳情請看: http://www.cnblogs.com/tristanguo/archive/2009/04/06/1430062.html

其它視圖注意事項:

<li>The item is: @Html.Raw(p)</li>表示對p不進行HTML編碼。

控制器可以返回本視圖,也可以返回其他視圖:
public ActionResult Index()
{
ViewBag.Message_ViewBag = "I am viewbag";
ViewData["Message_ViewData"] = "I am viewdata";

return View("About");
}
當我們需要返回指定完全不同目錄結構中的視圖時,可以這樣使用~符號來提供視圖的完整路徑來返回: return View("~/Views/Home/About.cshtml");

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM