學習ASP.NET有大約一個月了,一直都是半生不熟的,因為之前的很長時間都是在做java開發,沒有時間靜下來心來學習,加上ASP.NET的框架也很復雜,一時間也是看的昏頭轉向的,所以只能看到一點記錄一點,慢慢積累,慢慢總結吧。
Action向View傳遞數據很簡單,方式也很多,最直接的就是我們向View傳遞Model,這本身就是MVC的意義所在。如果是顯示一些消息,像是錯誤信息,可以使用ViewData:
public ActionResult Index() { ViewData["message"] = "Hello Word!"; return View(); }
然后是視圖:
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server"> <%: ViewData["message"]%> </asp:Content>
實際效果如:
我們可以看到,ViewData就是一個字典,它存放的是鍵值對。
既然Action可以向View傳遞數據,那么View是否可以修改數據然后再回傳給Action呢?
我們對代碼這樣修改:
public ActionResult Index() { ViewData["message"] = "Hello Word!"; return View(); } public ActionResult About() { string message = ViewData["message"] as string; if (message == "Hello") { ViewData["message2"] = "已經修改"; } else { ViewData["message2"] = "沒有修改"; } return View(); }
視圖:
為什么會這樣?因為ViewData只會在一次HTTP請求中有效,當這次請求結束后,就會自動清空其值。為什么呢?
因為ViewData的生命周期和所請求的View是一樣的,僅對當前View有效。
ViewBag也可以用來向視圖傳遞數據:
public ActionResult Index() { ViewBag.Message = "Hello, Word"; return View(); }
視圖:
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server"> <%: ViewBag.Message%> </asp:Content>
ViewBag的使用就相當於ViewData。
它跟ViewData一樣,都是字典值,但是內在的實現卻完全不一樣。
ViewBag最大的優點就是它不需要轉型就可以使用它里面的值,但ViewData需要這樣:
string message = ViewData["message"] as string;
因為ViewBag存放的不是鍵值對,而是dynamic動態類型,這是ASP.NET MVC3新增的部分。動態類型非常強大,尤其是容器的使用。
ViewBag就是封裝了的ViewData,它是順應C#4的dynamic關鍵字而誕生的。它可以讓我們像是屬性訪問一樣檢索字典中的值,這樣更加自然,這也是C#所倡導的:"可以讀出來的代碼"。
ViewBag在使用上與ViewData並沒有孰優孰劣的說法,但是可以肯定,ViewBag比ViewData要慢,但這個真心可以忽略。值得注意的是,ViewBag可以直接訪問存儲在ViewData里面的數據(因為它本來就只是封裝了的ViewData)。但是,像是這樣:
ViewData["Message hehe"] = "Hello, Word";
ViewBag就有心無力了。
更加重要的是,ViewBag無法作為擴展方法的參數,因為編譯器為了確保所選擇的擴展方法是正確的,編譯時必須知道參數的真正類型,所以,HTML輔助方法無法使用ViewBag。
除了上面兩種(其實是一種),還有一種方法,就是TempData。
TempData也是字典,所以它的使用完全等同於ViewData,但兩者之間還是存在很大的差異。
TempData,顧名思義,就是臨時數據。TempData保存在Session中,Controller每次請求的時候都會從Session中獲取TempData,然后清除Session。基於這樣的事實,在每次請求結束后,TempData的生命周期也就結束了。網上有一句話:TempData至多之只能通過一次Controller傳遞,假設我們的Controller是跳轉到下一個Controller,以此類推,在最后一個Controlle相應的視圖上,的確可以獲得該TempData。但是,這並不是說TempData已經跨請求傳遞了,這依然只是一次請求,至於是否是跨Controller傳遞,我認為不是,所謂的通過Controller傳遞,是指將TempData傳遞給View,在上面的例子中,只有最后的Controller才會將該TempData傳遞給View,所以,TempData的確是只能通過一次Controller傳遞。
TempData也可以在Action之間傳遞的,像是這樣:
public ActionResult Index() { TempData["message"] = "Hello"; return View(); } public ActionResult About() { if ("Hello" == TempData["message"] as string) { TempData["message"] = "Hello,Word"; } return View(); }
但必須注意,要使該行為正確,也就是TempData能夠被傳遞給另一個Action,Index操作對應的視圖就不能使用TempData,因為一旦使用就相當於一次請求,那么TempData中的值就會被清空。
TempData是存儲在Session中,但這個並不是絕對的,我們可以改變TempData的存儲地方,只要實現ITempDataProvider這個接口就行,但一般情況沒有必要這么做。