ViewData并不是像网上有些说的那样只在当前视图内有效,他的有效范围是在一个请求的生命周期内,而tempdata生命周期可以延续到紧跟后面的一个请求。
ViewData只是一个简单的字典,他的生存期跟Controller的生存期一样。请求进来被MvcHandler处理相应Controller被创建,这时Viewdata便存在,直到Controller被销毁,此时Viewdata也将不存在。因此只要是通过View()方法传递的视图名称都可以获得先前保存在其中的值。因为RedirectToAction最终调用的是RedirectToRouteResult()这样将会重新建立Controller因此当进行Redirect时Viewdata将不再可用。
来看看Tempdata被处理的过程:
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);
}
}
该方法是Controller的成员就是说每次请求被处理的时候,在action执行前调用TempDataDictionary的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();
}
在该方法中又调用TempDataProvider的LoadTempData()方法将这个回话的上次请求的Tempdata返回并把它从session中移除:
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);
}
}
然后开始执行action,在action中可能会把某些信息存放到Tempdata中,这时响应的键值会被添加到Tempdata的__modifiedKeys中。然后执行TempData.Save(ControllerContext, TempDataProvider)
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);
_modifiedKeys.Clear();
}
}
在该方法中将把没有修改的上次请求的Tempdata键值对移除然后调用 tempDataProvider.SaveTempData(controllerContext, _data)把Tempdata存放到Session中。