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中 ...
随机推荐
- 4、Orcal数据库dmp文件导入
1.CMD命令导入备份数据库dmp文件: 以上一篇博客提到的gdnh用户,我们需要在cmd窗口执行如下命令: imp gdnh/admin123@orcl file=E:/createTable.dm ...
- webpack 4 入坑及爬坑记录
一.安装 在本机安装好nodejs的基础上,window操作系统,cmd打开控制台,添加到创建的文件夹下 npm init //初始化npm npm install webpack --save-de ...
- 本地数据库导入线上服务器的mongodb中
更改默认端口 sudo vi /etc/mongod.conf 进入conf文件,修改port值为19999保存并退出. 重启mongodb sudo service mongod restart 进 ...
- 克隆linux虚拟机
背景:有时候,我们在用虚拟机的时候会用到多个进行使用.重新安装会花费大量的时间,此时,我们可以通过vmware虚拟机自带的功能快速克隆出完全相同的系统. 前提:被克隆的虚拟机系统要处于关闭状态 步骤: ...
- 1. Python中如何使用其他语言?(python的胶水作用,python又叫胶水语言)
1. python中如何插入C语言运行? (1)编写C语言代码: #include<stdio.h> void CFun() { printf("---------我是c语言:- ...
- 【洛谷P4719】动态dp 动态dp模板
题目大意:给你一颗$n$个点的树,点有点权,有$m$次操作,每次操作给定$x$,$y$,表示修改点$x$的权值为$y$. 你需要在每次操作之后求出这棵树的最大权独立集的权值大小. 数据范围:$n,m≤ ...
- vue、react、angular三大框架对比 && 与jQuery的对比
前端当前最火的三大框架当属vue.react以及angular了. 但是在做项目的时候,我们怎么去选择呢? 这里做一个比较,希望大家可以有一个比较清晰的认识. vue与react vue和react ...
- PreparedStatement插入values
public interface PreparedStatementextends Statement 表示预编译的 SQL 语句的对象. SQL 语句被预编译并存储在 PreparedStateme ...
- certificate verify fails (https://gems.ruby-china.org错误
首先:执行这一步报错的背景是: 更换gems源, 通常执行 gem sources --add https://gems.ruby-china.org/ --remove https://rubyge ...
- Android4.0 Launcher 源码分析3——WorkSpace结构(滑动)
3.WorkSpace结构(滑动) 桌面的左右滑动功能主要是在PagedView类中实现的,而WorkSpace是PagedView类的子类,所以会继承PagedView中的方法.当我们的手指点击Wo ...