控制器不外乎处理两件事:请求与响应,即一个请求要进行哪些处理,处理之后要进行什么样的响应。
2.1控制器向视图传递值(一)
用户除了第一次请求之外(如请求主页),其他后续请求的互动绝大部分都会通过View视图与Controller控制器来触发,而两者互动过程中最重要的一件事就是数据传递。数据传递有以下两个方向:
- Controller(控制器)传递至View(视图)
- View(视图)传递至Controller(控制器)
控制器Controller向视图View传递少量数据可以使用3种对象:ViewData、ViewBag、TempData。
2.1.1 ViewData对象
从底层定义角度来说,ViewData属性更加确切。
- ViewData属性
ViewData本身是ViewDataDictionary字典类型,而ViewDataDictionary类的定义如下:(其中object需要用时,强制类型转换)
public class ViewDataDictionary : IDictionary<string,object>{}
ViewDataDictionary类继承IDictionary<string,object>接口,这表示在ViewData中存放的是键/值对数据。ViewData只在一次HTTP请求中有效,当这次请求结束后,会自动清空其值。
2.ViewData的使用
控制器类HomeController.cs
public ActionResult Index(){
//使用ViewData从控制器传递文本数据到视图
ViewData["Message"] = "使用ViewData传递文本数据";
return View();
}
视图 Index.cshtml
<body>
/*Razor语法*/
<h2>@ViewData["Message"]</h2>
</body>
2.1.2 ViewBag对象
ViewBag对象是ASP .NET MVC 3 提供的功能,它被声明为一个dynamic类型。
- ViewBag属性
在ASP .NET MVC 5源代码中声明如下:
[Dynamic]
public dynamic ViewBag{get;}
一般类型是编译时就已经确定且不能在执行时修改,被称为静态类型。dynamic本身也是静态类型,千万不要被dynamic(动态)这个词混淆了,或者说是动态化的静态类型。它与静态类型的差异在于:dynamic对象会略过编译时静态类型的检查,而解析工作会在运行时进行(所以有错误也只有此阶段才知道)。大部分情况下,dynamic类型的行为就像object的类型一样,但是包含dynamic类型的操作编译器没有进行类型检查,编译器会将相关的信息进行封装,在之后使用时再用该信息来评估运行时的操作。
注意
dynamic类型的变量都会编译为object类型的变量。因此,dynamic类型只存在于编译时刻,而不存在于运行时刻。
2.ViewBag的使用
ViewBag属性在输入时使用"对象.属性"的输入方法,对于程序的代码编写而言,比字典更为直观。
控制器类HomeController.cs
public ActionResult Index(){
//使用ViewData从控制器传递文本数据到视图
ViewData["Message"] = "使用ViewData传递文本数据";
//使用ViewBag对象从控制器传递文本数据到视图
ViewBag.Name = "张三";
return View();
}
视图Index.cshtml
<body>
<h2>@ViewData["Message"]</h2>
//输出ViewBag对象的Name中保存的值
<h3>@ViewBag.Name</h3>
</body>
2.1.3 TempData对象
TempData属性是将数据存放在Session。
ViewData属性和ViewBag属性无法跨越Action()方法传递数据。当需要在Action()方法之间传递数据时,可采用TempData属性。
- TempData属性
TempData属性在ControllerBase类的定义如下:
public TempDataDictionary TempData {get;set;}
TempDataDictionary类的属性如下:
public class TempDataDictionary : IDictionary<string,object>{}
ASP .NET MVC 5 源代码追踪会发现TempData属性中数据的获取及存储最后均由SessionTempDataProvider类来处理。单从名称就可以很明显地看出TempData属性是将数据保存在Session中。
2. TempData的使用
控制器类HomeController.cs
public AcionResult Index(){
//使用TempData从控制器传递数据到下一个视图页面
TempData["Message"] = "使用TempData传递数据";
return View();
}
public ActionResult About(){
return View();
}
视图文件cshtml(Index)
<body>
<a href = "/Home/About">关于</a>
</body>
视图文件cshtml(About)
<body>
<h2>@TempData["Message"]</h2>
</body>
注意
控制器每次从Session中获取TempData后,就会清除Session中的TempData数据。在每次请求结束后,TempData的生命周期同时结束。
2.2 控制器向视图传递值(二)
2.2.1 ViewData对象、ViewBag对象传递 Model数据
因为ViewDataDictionary类型的内容可以存储任意数据,所以可以把整个Model数据放入ViewData对象或ViewBag对象中传递至View视图页。
例子:现有用户表User,查询表中的数据通过ViewData或ViewBag显示在视图页面上
控制器类HomeController.cs
using CLASS2.Models; //导入模型类命名
namespace CLASS2.Controllers{
public class HomeController : Controller{
//Model实体模型对象
fashionEntities db = new fashionEntities();
public ActionResult Index(){
//使用ViewData保存Model数据
ViewData["users"] = db.Users.ToList();
return View();
}
}
}
视图文件cshtml(Index)
<body>
<ul>
@foreach(var item in ViewData["users"] as List<CLASS2.Models.Users>){
<li>@item.username</li>
}
</ul>
</body>
2.3 视图传值到控制器
2.3.1 Request 对象
当需要从视图传递简单的数据至控制器中时,可以使用Request对象来完成。它是最原始的视图和后台之间的数据传递方式。
例子:
控制器类HomeController.cs
public ActionResult Index(){
return View();
}
[HttpPost]
public ActionResult Save(){
string name = Request["username"];
ViewBag.Message = "您输入的名称是:"+name;
return View();
}
视图文件cshtml(Index)
<body>
<form method="post" action="Save">
用户名:<input type="text" name="username" />
<input type="submit" value="提交" />
</form>
</body>
视图文件cshtml(Save)
<body>
<h2>@ViewBag.Message</h2>
</body>