一.摘要
本文讲解在Act
二.承上启下
上一篇文章中我们学习了Controller处理一次请求的全过程.在Controller的Act
下面首先让我们学习如何将Model传递给View对象.
三.传递数据给View
在MVC中,Model对象是指包含了数据的模型. Controller将Model传递给View以后, View对象中不应该做任何的业务逻辑处理, 仅仅根据Model对象做一些显示逻辑的处理.
传递Model对象时, 我们有两种选择:
1.传递一个弱类型的集合, 即成员为object类型的集合, 在View中需要将每个成员转换成我们需要的类型,比如int, string,自定义类型等.
2.传递强类型对象, 这些类型是我们自定义的. 在View中直接使用我们传递的强类型对象, 不需要再转换类型.
如果让我们自己设计一个MVC框架, 我们也会想到上面两种实现方式,接下来看看在ASP.NET MVC中的实现.
1.传递弱类型的集合
(1) 如何传递
ASP.NET MVC框架定义了ViewContext类, 直译后是"View上下文", 其中保存和View有关的所有数据, 其中Model对象也封装在了此类型中.
ViewContext对象包含三个属性:
- IView View
- ViewDataDictionary ViewData
- TempDataDictionary TempData
其中ViewData集合和TempData集合都是用来保存Model对象的.在一个Controller的Act
/// <summary> /// 传递弱类型Model的Action示例 /// </summary> /// <returns>ViewResult</returns> public ActionResult WeakTypedDemo() { ViewData["model"] = "Weak Type Da ta in ViewData"; TempData["model"] = "Weak Type Da ta in TempData"; return View("WeakTypedDemo"); }
在页面中, 是用如下方式使用这两个集合:
<div> <% = ViewData["model"] %><br /> <% = TempData["model"] %><br /> </div>
(2) 传递过程
请注意Act
protected internal virtual ViewResult View(IView view, object model) { if (model != null) { ViewData.Model = model; } return new ViewResult { View = view, ViewData = ViewData, TempData = TempData }; }
然后在ViewResult中根据ViewData和TempData构建ViewContext对象:
public override void ExecuteResult(ControllerContext context) { //... ViewContext viewContext = new ViewContext(context, View, ViewData, TempData); View.Render(viewContext, context.HttpContext.Response.Output); //... }
ViewContext对象最终会传递给ViewPage, 也就是说ViewData和TempData集合传递到了ViewPage. 我这里简化了最后的传递流程, 实际上ViewData对象并不是通过ViewContext传递到ViewPage中的, ViewPage上的ViewData是一个单独的属性, 并没有像TempData一样其实访问的是ViewContext.TempData. 这么做容易产生奇异, 本类ViewContext是一个很好理解职责十分清晰的类. 作为使用者的我们暂时可以忽略这点不足, 因为如此实现ViewData完全是为了下面使用强类型对象.
(3)ViewData和TempData的区别
虽然ViewData和TempData都可以传递弱类型数据,但是两者的使用是有区别的:
- ViewData的生命周期和View相同, 只对当前View有效.
- TempData保存在Session中, Controller每次执行请求的时候会从Session中获取TempData并删除Session, 获取完TempData数据后虽然保存在内部的字典对象中,但是TempData集合的每个条目访问一次后就从字典表中删除. 也就是说TempData的数据至多只能经过一次Controller传递.
(4) TempData的实现
TempData的类型是TempDataDictionary, 和一般的字典表没有明显的不同, TempData的生命周期是由Controll决定的.
在所有Controll的基类ControllerBase中, 创建了类型为TempDataDictionary的TempData属性.
在ControllerBase的派生类Controller中, 重写了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, TempDataPro