小程序教程

ASP.NET MVC TempData使用心得

字号+ 作者:H5之家 来源:H5之家 2017-01-08 11:02 我要评论( )

ASP.NET MVC TempData使用心得 在看TempData的說明時,有人說用一次就刪除,有人說一個Request就結束,在道聽途說下,有一次我的Code就出了Bug,一直死在TempData,最後看Source Code才發現,我對TempData的認知出了錯誤。 原理在ASP.NET MVC中資料傳遞主要

ASP.NET MVC TempData使用心得

在看TempData的說明時,有人說用一次就刪除,有人說一個Request就結束,在道聽途說下,有一次我的Code就出了Bug,一直死在TempData,最後看Source Code才發現,我對TempData的認知出了錯誤。



原理在ASP.NET MVC中資料傳遞主要有ViewData與TempData,ViewData主要是Controller傳遞Data給View,存留期只有一個Action,要跨Action要使用TempData,而TempData依TempDataProvider的不同,會有不同的存留期,預設的TempDataProvider是SessionStateTempDataProvider,你沒有看錯,預設是用Session來存放TempData,Session不是使用者存放資料,而且存留時間預設在20分鐘的嗎?

所以SessionStateTempDataProvider有做一些手段,Controller起來時,從Session載入TempData,然後刪除Session,所以在Action時是不會看到TempData的Session,在讀取TempData時,會記錄用了那些Key,在Controller結束時,會把沒有過的TempData在存回Session中,所以一直沒有讀取的TempData是會存在到Session消失的。

Note:

ViewData的存留期測試

HomeController.cs 片段 public ActionResult Index() { this.ViewData["Data"] = "Index"; return View(); } public ActionResult List() { //什麼Data都沒有輸出 return View(); }Index.aspx 片段 <div> Partial: <% //ViewData是使用Index,不會執行List的Action Html.RenderPartial("List"); %> </div> <div> Action: <% //ViewData是使用List,會執行List的Action Html.RenderAction("List"); %> </div> List.ascx 片段 <%:this.ViewData["Data"] %>


結果





執行Partial或RanderPartial是在同一個Action中直接呼叫View,共用同一個ViewData。

執行Action或RanderAction會呼叫另一個Action,那一個Action再呼叫View,使用不用的ViewData。

如果要在不同的Action中傳遞資料,要使用TempData。


錯誤重現下列這段Code,猜猜有什麼Bug。

public ActionResult Index() { this.TempData["UseDefault"] = "true"; return View(); } public ActionResult List() { //在Index的View,會使用RanderAction呼叫List,但那一個區塊是會用Ajax重載 if (this.TempData.ContainsKey("UseDefault")) { //從Index的View,使用RanderAction呼叫,使用預設值 .......... } else { //從Ajax呼叫 ........... } return View(); }


































答案是

呼叫this.TempData.ContainsKey("UseDefult")一直都是True,因為ContainsKey不是使用,所以TempData["UseDefult"]會一直保留在Session,直到Session消失前都是true,所以從Ajax呼叫一直都是使用預設值。



原始碼分析載入與儲存時機

System.Web.Mvc.Controller.cs 片段 protected override void ExecuteCore() { //載入TempData PossiblyLoadTempData(); try { //呼叫Action ........... } finally { //儲存TempData PossiblySaveTempData(); }


TempData的一些操作

System.Web.Mvc.TempDataDictionary.cs 片段 //_data 是放Keys + Values //_initialKeys 是放Keys,使用時移除Key //_retainedKeys 是放有呼叫,Keep的Keys public void Load(ControllerContext controllerContext, ITempDataProvider tempDataProvider) { //載入放在Provider的資料 IDictionary<string, object> providerDictionary = tempDataProvider.LoadTempData(controllerContext); _data = (providerDictionary != null) ? new Dictionary<string, object>(providerDictionary, StringComparer.OrdinalIgnoreCase) : new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); _initialKeys = new HashSet<string>(_data.Keys, StringComparer.OrdinalIgnoreCase); _retainedKeys.Clear(); } public void Save(ControllerContext controllerContext, ITempDataProvider tempDataProvider) { //keysToKeep = _initialKeys + _retainedKeys string[] keysToKeep = _initialKeys.Union(_retainedKeys, StringComparer.OrdinalIgnoreCase).ToArray(); //keysToRemove = _data - keysToKeep string[] keysToRemove = _data.Keys.Except(keysToKeep, StringComparer.OrdinalIgnoreCase).ToArray(); //刪除使用過且不保留的Keys foreach (string key in keysToRemove) { _data.Remove(key); } //將沒有使用的TempData存起來 tempDataProvider.SaveTempData(controllerContext, _data); } public object this[string key] { get { object value; if (TryGetValue(key, out value)) { //讀取時刪除Key,在Save時用來比較 _initialKeys.Remove(key); return value; } return null; } set { _data[key] = value; _initialKeys.Add(key); } } public void Keep(string key) { //保留Key _retainedKeys.Add(key); }


Note:

我曾經想過寫一個Provider,資料是存放在HttpContext.Items,因為我習慣Temp的資料,在一個Request結束後就消失,不過專案成員們都覺得太多此一舉了,而作罷。

//自訂的TempDataProvider,沒辦法用設定改變(至少我沒找到),只能用繼承來覆寫CreateTempDataProvider作到統一使用 public class MyControllerBase : Controller { protected override ITempDataProvider CreateTempDataProvider() { return new HttpContextItemsTempDataProvider(); } } //使用 public class HomeControllerBase : MyControllerBase { }




參考資料

[CodePlex]ASP.NET MVC
[MSDN]ASP.NET MVC 2

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • Asp.net 自带报表的使用详解

    Asp.net 自带报表的使用详解

    2016-12-21 18:10

  • ASP.NET Ajax – History Support 續

    ASP.NET Ajax – History Support 續

    2016-12-14 17:02

  • 微信小程序开发工具使用与设计规范(二)

    微信小程序开发工具使用与设计规范(二)

    2016-11-23 09:49

  • 微信小程序TabBar底部栏的使用

    微信小程序TabBar底部栏的使用

    2016-11-23 09:49

网友点评