深入分析 ASP.NET Mvc 1.0 – 2. Controller.Execute(Request)-TempDataDictionary的Load与Save操作
来源:互联网 发布:Mac梦幻西游 编辑:程序博客网 时间:2024/05/29 09:17
Controller最终是通过调用ControllerBase类的Execute(RequestContext)方法来完成一个Action的创建与执行操作, 代码如下:
protected virtual void Execute(RequestContext requestContext) { if (requestContext == null) { throw new ArgumentNullException("requestContext"); } Initialize(requestContext); ExecuteCore(); }
代码分为两步:
- Initialize(requestContext): 创建ControllerContext类的一个实例。
- ExecuteCore(): 加载TempData, 创建及执行Action,处理Action返回的ActionResult , 保存TempData数据。
ExecuteCore()的代码如下:
protected override void ExecuteCore() { TempData.Load(ControllerContext, TempDataProvider); try { string actionName = RouteData.GetRequiredString("action"); if (!ActionInvoker.InvokeAction(ControllerContext, actionName)) { HandleUnknownAction(actionName); } } finally { TempData.Save(ControllerContext, TempDataProvider); } }
代码又分为三个部分:
- TempData.Load(ControllerContext, TempDataProvider): 从HttpContextBase.Session中加载TempData数据
- ActionInvoker.InvokeAction(ControllerContext, actionName): 创建,执行Action,并处理Action返回的ActionResult
- TempData.Save(ControllerContext, TempDataProvider): 保存TempData
第1, 第3部分都是对TempData的操作,下面的文字将详细介绍这两个步骤。
1. TempData.Load(ControllerContext, TempDataProvider)
TempDataProvider: 就是SessionStateTempDataProvider,他是一个继承了ITempDataProvider接口的Session辅助类
TempDataProvider.Load的源码:
public void Load(ControllerContext controllerContext, ITempDataProvider tempDataProvider) { 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); _modifiedKeys.Clear(); }这里就是加载TempData的全部过程:
- 调用SessionStateTempDataProvider中的LoadTempData(…)方法并近回一个IDictionary<string, object>对象
- 初始化_data对象,如果providerDictionary不是null那么把providerDictionary中的数据存放到_data对象中,其实这个_data就是TempData用来保存数据的容器,
- 初始化_initialKeys对象并将_data中的全部Key值放入其中,它用来缓存已加载的Key值,如果对TempData中插入新数据时, _initialKeys对象中的数据不会有任务变化
- 清除_modifiedKeys中的值,用来保存TempData新的Key值,当有一个新的键值对插入到TempData中,这个key值会被保存到_modifiedKeys对象中
再来深入tempDataProvider.LoadTempData(controllerContext)方法,其实就是SessionStateTempDataProvider类中的LoadTempData(…)方法:
public virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext) { HttpContextBase httpContext = controllerContext.HttpContext; if (httpContext.Session == null) { throw new InvalidOperationException(MvcResources.SessionStateTempDataProvider_SessionStateDisabled); } Dictionary<string, object> tempDataDictionary = httpContext.Session[TempDataSessionStateKey] as Dictionary<string, object>; if (tempDataDictionary != null) { // If we got it from Session, remove it so that no other request gets it httpContext.Session.Remove(TempDataSessionStateKey); return tempDataDictionary; } else { return new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); } }SessionStateTempDataProvider类中定义了一个常量,用它来作为保存在Session中TempData对象的Key。
internal const string TempDataSessionStateKey = "__ControllerTempData";在LoadTempData(…)方法中, 首先在Session中查找与key相对应的Dictionary<string, object>对象,如果Session中存在这个对象,那么就清除Session中的这个键值对并返回找到的Dictionary<string, object>对象, 否则创建一个新的Dictionary<string, object>对象并返回。
这里的重点就是httpContext.Session.Remove(TempDataSessionStateKey) 方法,这也是TempData的特点,即同一个TempData只能被传递一次。当在Session中找到TempData后立即将它从Session中清除掉,下一次执行LoadTempData(…)方法时绝不会再找到同一个TempData。
再次说明:只要将一个键值对放入到TempData中,不论是同一个Controller中的不同Action,还是不同Controller中的不同Action都可以接收到这个TempData,但是仅此一次,当程序再次提交回服务端后是绝不可能再获得同样的值的TempData对象, 因为它已经在Session中被清除掉。
2. TempData.Save(ControllerContext, TempDataProvider)
这是整个Controller.Execute(…)生命周期中最后一个操作, 它的作用是保存新的TempData到HttpContext.Base.Session中。Save方法的具体代码:
public void Save(ControllerContext controllerContext, ITempDataProvider tempDataProvider) { if (_modifiedKeys.Count > 0) { // Apply change tracking. foreach (string x in _initialKeys) { if (!_modifiedKeys.Contains(x)) { _data.Remove(x); } } // Store the dictionary tempDataProvider.SaveTempData(controllerContext, _data); } }
上面提到过_initialKeys和_modifiedKeys的重要性,它们的作用在这里将体现出来,
- _initialKeys: 保存在Action执行之前TempData中的全部Key值,如果在action执行过程中有新的键值对插入到TempData中, 对_initialKeys对象中的值不会有任何影响。
- _modifiedKeys: 在Action执行过程中, 如果有新的键值对插入到TempData中,这个新的Key会插入到_modifiedKeys对象中。
Save方法中首先判断_modifiedKeys对象中元素的数量,是否有新的键值对被插入到TempData中,foreach和下面的if语句是从TempData中删除无用的键值对数据,最后调用 tempDataProvider.SaveTempData(controllerContext, _data)方法,将TempData保存在HttpContextBase.Session中。
注意:在加载TempData过程中会将上次定义的TempData中数据放入到_data中,这里的foreach, if语句是去掉不再需要传递的键值对,确保TempData中仅保留本次Action执行过程中产生的键值对数据。
- 深入分析 ASP.NET Mvc 1.0 – 2. Controller.Execute(Request)-TempDataDictionary的Load与Save操作
- 深入分析ASP.NET Mvc 1.0 – 1. 深入MvcHandler
- 从零开始学习 ASP.NET MVC 1.0 (三) Controller/Action 深入解析与应用实例
- 从零开始学习 ASP.NET MVC 1.0 (三) Controller/Action 深入解析与应用实例
- Asp.net mvc Controller与 View之间的传递
- mock Request on Controller in ASP.Net MVC ?
- ASP.NET MVC 4 Controller与Action
- 深入分析 ASP.NET Mvc 深入MvcHandler
- ASP.NET MVC Controller与Areas下面的Controller同名的解决办法
- ASP.NET MVC Controller的激活机制
- ASP.NET MVC Controller的激活
- ASP.NET MVC Controller的激活
- .NET下枚举类型的Save和Load分析
- 关于Controller下Request取值的问题(.net mvc)
- Asp.net MVC 示例项目"Suteki.Shop"分析之---Controller
- Asp.net MVC 示例项目"Suteki.Shop"分析之---Controller
- asp.net mvc源码分析-Controller篇 ValueProvider
- asp.net MVC Controller 小记
- 基于jQuery实现的当离开页面时出现提示的实现代码
- 源代码行数统计工具 Any Code Counter
- Android 视频播放器截屏功能实现讲解
- ios 视图切换动画效果
- Java 直接选择排序算法
- 深入分析 ASP.NET Mvc 1.0 – 2. Controller.Execute(Request)-TempDataDictionary的Load与Save操作
- Android应用程序组件Content Provider在应用程序之间共享数据的原理分析
- LinQ To Xml
- 服务器获得客户端提交的数据及中文乱码问题
- Android应用程序组件Content Provider的启动过程源代码分析
- OpenCV学习笔记(三十六)——Kalman滤波做运动目标跟踪
- Ant的一些知识
- COM载板设计之一: PCB的设计
- md5sum的使用