ASP.NET MVC传递Model到视图的多种方式总结(二)__关于ViewBag、ViewData和TempData的实现机制与区别
在ASP.NET MVC中,视图数据可以通过ViewBag、ViewData、TempData来访问,其中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
ViewBag 不再是字典的键值对结构,而是 dynamic 动态类型,它会在程序运行的时候动态解析。
控制器代码:
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,则会出现如下错误:

这时如果我们希望使用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
(TempData默认是使用Session来存储临时数据的,TempData中存放的数据只一次访问中有效,一次访问完后就会删除了的。这个一次访问指的是一个请求到下一个请求,因为在下一个请求到来之后,会从Session中取出保存在里面的TempData数据并赋值给TempData,然后将数据从Session中删除。我们看一下ASP.NET MVC Preview5源码:

也就是说TempData只保存到下一个请求中,下一个请求完了之后,TempData就会被删除了。注意这里TempData使用Session来做存储的,Session是对应特定用户的,所以并不存在并发问题。
若想TempData中的数据在访问下一个请求后不被删除,则可以使用TempData.Keep()方法。)
其它视图注意事项
<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");
参考链接:https://www.cnblogs.com/bianlan/archive/2013/01/11/2857105.html
ASP.NET MVC传递Model到视图的多种方式总结(二)__关于ViewBag、ViewData和TempData的实现机制与区别的更多相关文章
- ASP.NET MVC传递Model到视图的多种方式总结
ASP.NET MVC传递Model到视图的多种方式总结 有多种方式可以将数据传递到视图,如下所示: ViewData ViewBag PartialView TempData ViewModel T ...
- ASP.NET MVC传递Model到视图的多种方式之通用方式的使用
ASP.NET MVC传递Model到视图的多种方式总结——通用方式的使用 有多种方式可以将数据传递到视图,如下所示: ViewData ViewBag PartialView TempData Vi ...
- ASP.NET MVC传递Model到视图的多种方式总结(一)__通用方式的使用
有多种方式可以将数据传递到视图,如下所示: ViewData ViewBag PartialView TempData ViewModel Tuple 场景: 在视图页面,下拉框选择课程触发事件,分别 ...
- ASP.NET MVC 3 Model【通过一简单实例一步一步的介绍】
今天主要讲Model的两个方面: 1. ASP.Net MVC 3 Model 简介 通过一简单的事例一步一步的介绍 2. ASP.Net MVC 3 Model 的一些验证 MVC 中 Model ...
- ASP.NET MVC 之Model的呈现
ASP.NET MVC 之Model的呈现(仅此一文系列三) 本文目的 我们来看一个小例子,在一个ASP.NET MVC项目中创建一个控制器Home,只有一个Index: public class H ...
- Asp.net MVC的Model Binder工作流程以及扩展方法(2) - Binder Attribute
上篇文章中分析了Custom Binder的弊端: 由于Custom Binder是和具体的类型相关,比如指定类型A由我们的Custom Binder解析,那么导致系统运行中的所有Action的访问参 ...
- Asp.net MVC的Model Binder工作流程以及扩展方法(1) - Custom Model Binder
在Asp.net MVC中, Model Binder是生命周期中的一个非常重要的部分.搞清楚Model Binder的流程,能够帮助理解Model Binder的背后发生了什么.同时该系列文章会列举 ...
- [转]ASP.NET MVC 2: Model Validation
本文转自:http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx?CommentPo ...
- Asp.net MVC的Model Binder工作流程以及扩展方法(1)
Asp.net MVC的Model Binder工作流程以及扩展方法(1)2014-03-19 08:02 by JustRun, 523 阅读, 4 评论, 收藏, 编辑 在Asp.net MVC中 ...
随机推荐
- 主机安全扫描工具-- vuls
https://vuls.io/ 一. 安装 系统管理员有责任定期去检查系统的弱点和更新软件, vuls 可以提供如下功能: 通知管理员机器有安全隐患 支持本地和远程扫描(需要有 ssh 权限) 可以 ...
- 微信小程序redirect 到tab不刷新
// 更新2018/11/20:现在小程序的页面栈长度为10 更正 2018/11/20: 经过一段时间的实践,我发现以前方法存在很多问题,比如 getCurrentPages 方法并不在官方的 AP ...
- Java Web之Servlet中response、request乱码问题解决
Java Web之Servlet中response.request乱码问题解决 一.request请求参数出现的乱码问题 get请求: get请求的参数是在url后面提交过来的,也就是在请求行中, ...
- 4. Neural Network
1. 神经网络 首先引入一些便于稍后讨论的新标记: $L$:代表神经网络层数$S_l$:代表第$l$层处理单元的个数$K$:代表多分类中类别种数 2. 前向传播(forward propagation ...
- postgresql 脏读-dirtied
共享缓冲区 在内存中读取或写入数据总是比在任何其他介质上更快.数据库服务器还需要用于快速访问数据的内存,无论是READ还是WRITE访问.在PostgreSQL中,这被称为"共享缓冲区&qu ...
- 【learning】 单调队列与单调栈用法详解
1.单调栈 单调栈是指一个栈内部的元素具有严格单调性的一种数据结构,分为单调递增栈和单调递减栈. 其具有以下两个性质: 1,满足栈底到栈顶的元素具有严格单调性. 2,满足栈的先进后出特性,越靠近栈顶的 ...
- IO概述、异常、File文件类_DAY19
IO概述: 操作数据的工具 IO流,即数据流,数据像水流一样通过IO工具进行传输. 程序 <IO> 硬盘 绝对路径与相对路径 1:异常(理解) (1)就是程序的非正常情况. 异常相关 ...
- android Service 学习总结
学习android开发已经四五个月,由于项目中职责的原因一直没有接触过Service的实际项目,今天重新学一遍Service用法. 问题: 作为四大组件,为什么需要Service? 它与Thread又 ...
- 开源微信支付SDK
应该有一年多没在博客园上写文章了,毕竟是一个记录自己技术成长的平台,没能将写博客长期坚持下来,说起来也是挺惭愧的.对于自己的近况而言,确实平常加班也比较多,时间会比较压缩,所以到后来博客也基本停止了更 ...
- Spring Security构建Rest服务-0500-异步处理rest服务
异步处理REST服务: 1,使用Runnable异步处理Rest服务 2,使用DeferredResult异步处理Rest服务 3,异步处理配置 异步处理能提高服务器的吞吐量. 一.使用Runnabl ...