ASP.NET MVC 4 (二)控制器
MVC中控制器负责处理请求,由它操作数据模型,最后返回视图给用户。
IController接口
所有的控制器类以Controller结尾,必须实现System.Web.Mvc.IController接口,一个最简单的控制器类可以是:
public class BasicController : IController {
        public void Execute(RequestContext requestContext) {
            string controller = (string)requestContext.RouteData.Values["controller"];
            string action = (string)requestContext.RouteData.Values["action"];
            if (action.ToLower() == "redirect") {
                requestContext.HttpContext.Response.Redirect("/Derived/Index");
            } else {
                requestContext.HttpContext.Response.Write(
                    string.Format("Controller: {0}, Action: {1}",
                    controller, action));
            }
        }
    }
BasicController类实现了IController的唯一方法Execute(),在上面的例子中直接返回数据到请求响应,我们可以根据自己的需求来灵活的处理客户请求。
Controller类
更多的时候我们直接继承MVC已经定义的控制类System.Web.Mvc.Controller:
public class DerivedController : Controller
{ public ActionResult Index()
{
ViewBag.Message = "Hello from the DerivedController Index method";
return View("MyView");
} }
Controller类封装的IController.Execute()方法会调用我们定义的Action方法,比如这里的Index()。Controller同时为我们提供了众多的属性来方便获取相关数据:
- Request:比如Request.QueryString、Request.Url、Request.Form、Request.HttpMethod等。
 - Response:可以直接向Response返回数据到用户。
 - RouteData:和路径映射相关的数据,比如RouteData.Route、RouteData.Values。
 - HttpContext:比如HttpContext.HttpSessionStateBAse、HttpContext.Items。
 - User:当前已会话已认证的用户信息。
 - TempData:存储当前用户的一些临时信息,可以传递给View。
 
一些获取Controller数据的例子:
string userName = User.Identity.Name;
string serverName = Server.MachineName;
string clientIP = Request.UserHostAddress;
DateTime dateStamp = HttpContext.Timestamp;
AuditRequest(userName, serverName, clientIP, dateStamp, "Renaming product");
// Retrieve posted data from Request.Form
string oldProductName = Request.Form["OldName"];
string newProductName = Request.Form["NewName"];
bool result = AttemptProductRename(oldProductName, newProductName);
ViewData["RenameResult"] = result;
return View("ProductRenamed");
Action方法参数
控制器Action方法可以带一系列的参数,比如:
...
public ActionResult ShowWeatherForecast(string city, DateTime forDate) {
// ... implement weather forecast here ...
return View();
}
...
这些参数是由MVC的Value providers和model binders所提供的,MVC自动从请求数据等中自动按名称为我们解析参数值并做类型转换,比如上面例子中的city和forDate可能来自于:
string city = (string)RouteData.Values["city"];
DateTime forDate = DateTime.Parse(Request.Form["forDate"]);
响应输出
我们可以从Icontroller的Excecute()方法中直接输出响应,也可以在Controller中使用Response直接输出响应:
public void ProduceOutput()
{
if (Server.MachineName == "TINY")
{
Response.Redirect("/Basic/Index");
}
else
{
Response.Write("Controller: Derived, Action: ProduceOutput");
}
}
这里的Action方法ProduceOutput没有返回值,更多的时候,我们返回一个ActionResult对象,比如View("MyView")返回一个ViewResult,ViewResult继承自ActionResult。甚至我们可以创建自定义的ActionResult类来使用:
public class CustomRedirectResult : ActionResult {
  public string Url { get; set; }
  public override void ExecuteResult(ControllerContext context) {
  string fullUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext);
  context.HttpContext.Response.Redirect(fullUrl);
  }
} 
在控制器Action方法中返回自定义的ActionResult对象:
public ActionResultProduceOutput() {
  if (Server.MachineName == "TINY") {
      return new CustomRedirectResult { Url = "/Basic/Index" };
    } else {
      Response.Write("Controller: Derived, Action: ProduceOutput");
      return null;
    }
} 
这里创建了一个实现重定向的ActionResult对象,实际上MVC已经为我们提供了RedirectResult来实现这个功能:
...
public ActionResult ProduceOutput() {
return new RedirectResult("/Basic/Index");
}
...
或者更方便的调用Controller的Redirect()方法:
...
public ActionResult ProduceOutput() {
return Redirect("/Basic/Index");
}
...
除了RedirectResult,MVC还提供这些ActionResult:
- ViewResult:渲染一个视图,等同于控制器中调用View()
 - PartialViewResult:渲染部分视图,等同于控制器中调用PartialView()
 - RedirectToRouteResult:根据指定的路由信息发出一个HTTP 301或者302重定向命令,等同于控制器调用RedirectToAction 、RedirectToActionPermanent 、RedirectToRoute 、RedirectToRoutePermanent。
 - HttpUnauthorizedResult:设置HTTP状态码401表示未授权。
 - HttpNotFoundResult:返回HTTP 404-NOT FOUD错误,等同于控制器调用HttpNotFound()。
 - HttpStatusCodeResult:返回自定义的HTTP状态码
 - EmptyResult:不返回任何信息。
 
返回视图
用得最多的就是在控制器Action方法中返回一个视图,由它渲染HTML返回给用户。我们可以不带任何参数调用View(),MVC会查找和Action方法同名(不带Controller)的View,也可以直接在参数中指定视图的名称:
public ViewResult Index() {
  return View("Homepage");
} 
MVC在应用目录下搜索视图,如果启用了区域Area,搜索路径为:
• /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.aspx
• /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.ascx
• /Areas/<AreaName>/Views/Shared/<ViewName>.aspx
• /Areas/<AreaName>/Views/Shared/<ViewName>.ascx
• /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.cshtml
• /Areas/<AreaName>/Views/<ControllerName>/<ViewName>.vbhtml
• /Areas/<AreaName>/Views/Shared/<ViewName>.cshtml
• /Areas/<AreaName>/Views/Shared/<ViewName>.vbhtml
如果没有使用Area,搜索路径为:
• /Views/<ControllerName>/<ViewName>.aspx
• /Views/<ControllerName>/<ViewName>.ascx
• /Views/Shared/<ViewName>.aspx
• /Views/Shared/<ViewName>.ascx
• /Views/<ControllerName>/<ViewName>.cshtml
• /Views/<ControllerName>/<ViewName>.vbhtml
• /Views/Shared/<ViewName>.cshtml
• /Views/Shared/<ViewName>.vbhtml
MVC如果按照上述顺序搜索视图,如果找到一个文件就停止搜索,如果没有可用的视图文件会返回资源未找到错误。注意MVC会搜索ASPX视图引擎的老式文件.aspx和.ascx。
View方法还有其他一些重载调用方式:
return View("Index", "_AlternateLayoutPage"); //指定要使用的布局模板
return View("~/Views/Other/Index.cshtml"); //直接指定要使用的视图模板,必须以/或者~/开头。
从控制器向视图传递数据
我们可以在调用View()直接指定要传递给视图的数据:
...
public ViewResult Index() {
DateTime date = DateTime.Now;
return View(date);
}
...
在视图中使用传入的数据:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
The day is: @(((DateTime)Model).DayOfWeek) 
对于强类型的视图,使用起来更方便:
@model DateTime
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
The day is: @Model.DayOfWeek
也可以使用ViewBag来传递,它是一个动态的键值对集合:
public ViewResult Index() {
ViewBag.Message = "Hello";
ViewBag.Date = DateTime.Now;
return View();
} 
在视图中使用:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
The day is: @ViewBag.Date.DayOfWeek
<p />
The message is: @ViewBag.Message 
Viewbag比视图模型好在可以传递多个值,但是VS不会给出IntelliSense提示,只会在渲染视图时给出错误信息。
重定向
在上面我们已经看到可以使用Redirect重定向请求:
public RedirectResult Redirect() {
return Redirect("/Example/Index");
} 
也可以使用RedirectPermanent永久重定向:
return RedirectPermanent("/Example/Index");
和Redirect临时重定向发出302 HTTP代码不同,RedirectPermanent发回301 HTTP代码,前者指示浏览器重新GET新的URL,而后者指示浏览器缓存重定向信息,以后针对老URL的请求自动转向新URL。
除了重定向到URL,我们可以重定向到路径映射方法:
public RedirectToRouteResult Redirect() {
  return RedirectToRoute(new { controller = "Example", action = "Index", ID = "MyID" });
} 
或者一个Action方法:
public RedirectToRouteResult RedirectToRoute() {
    return RedirectToAction("Index");
} 
可以指定是某个控制器的某个Action方法:
public RedirectToRouteResult Redirect() {
    return RedirectToAction("Index", "Basic");
}  
如果在重定向另一个控制器的Action时我们想要传递数据该怎么办呢?我们可以使用TempData:
public RedirectToRouteResult RedirectToRoute() {
TempData["Message"] = "Hello";
TempData["Date"] = DateTime.Now;
return RedirectToAction("Index");
} 
在新的视图中读取TempData:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
The day is: @(((DateTime)TempData["Date"]).DayOfWeek)
<p />
The message is: @TempData["Message"]
和ViewBag只用于控制器和同名视图不同,TempData类似于会话Session数据,可以在不同控制器/视图中共享,但是和Session跨请求不同的是一旦读取了TempData的数据TempData就会被删除。TempData.Peek读取数据但是不删除数据:
DateTime time = (DateTime)TempData.Peek("Date"); 
TempData.Keep可以标记数据不被删除,但是如果再被读取又会再次标记删除,类似于引用计数器:
TempData.Keep("Date"); 
返回HTTP状态码
我们可以返回一个HTTP状态码比如404错误:
public HttpStatusCodeResult StatusCode() {
return new HttpStatusCodeResult(, "URL cannot be serviced");
} 
或者直接调用:
return HttpNotFound();
401未授权错误:
return new HttpUnauthorizedResult();
以上为对《Apress Pro ASP.NET MVC 4》第四版相关内容的总结,不详之处参见原版 http://www.apress.com/9781430242369。
ASP.NET MVC 4 (二)控制器的更多相关文章
- ASP.NET MVC 视图(二)
		
ASP.NET MVC 视图(二) 前言 上篇中对于视图引擎只是做了简单的演示,对于真正的理解视图引擎的工作过程可能还有点模糊,本篇将会对由MVC框架提供给我们的Razor视图引擎的整个执行过程做一个 ...
 - ASP.NET MVC学习之控制器篇扩展性
		
原文:ASP.NET MVC学习之控制器篇扩展性 一.前言 在之前的一篇随笔中已经讲述过控制器,而今天的随笔是作为之前的扩展. 二.正文 1.自定义动作方法 相信大家在开发过程一定会遇到动作方法的重名 ...
 - ASP.NET MVC 5  04 - 控制器
		
PS: 唉.本来这一篇前几天早就应该发了的,可是谁每月没有那么几天啊... 呵呵.开个玩笑.反正就是各种烦气,所以也就一直没上来继续发了. 年底了,摆正一下心态吧.好好干,整点钱,过年回家能跟亲朋好友 ...
 - ASP.NET MVC 路由(二)
		
ASP.NET MVC路由(二) 前言 在上一篇中,提及了Route.RouteCollection对象的一些信息,以及它们的结构所对应的关系.按照处理流程走下来还有遗留的疑问没有解决这个篇幅就来讲 ...
 - ASP.NET MVC 5 -从控制器访问数据模型
		
在本节中,您将创建一个新的MoviesController类,并在这个Controller类里编写代码来取得电影数据,并使用视图模板将数据展示在浏览器里. 在开始下一步前,先Build一下应用程序(生 ...
 - asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析
		
下面我用一个实例来和大家分享一下我的经验,asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析. using Newtonsoft.Json; usin ...
 - 【ASP.NET MVC系列】浅谈ASP.NET MVC 视图与控制器传递数据
		
ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...
 - [转]ASP.NET MVC 5 -从控制器访问数据模型
		
在本节中,您将创建一个新的MoviesController类,并在这个Controller类里编写代码来取得电影数据,并使用视图模板将数据展示在浏览器里. 在开始下一步前,先Build一下应用程序(生 ...
 - ASP.NET MVC学习之控制器篇(二)
		
原文链接:http://www.asp.net/learn/mvc/ 这篇教程探索了ASP.NET MVC控制器(controller).控制器动作(controller action)和动作结果(a ...
 
随机推荐
- mysq在某一刻同时获取主从库的位置点
			
在从库进行锁表操作flush table with read lock, 通过show slave status\G 获取对应主库的位置点: show slave status\G********** ...
 - buzhoutiao
			
基于SUI前端框架 前台HTML: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " ...
 - 小程序的tab标签实现效果
			
swiper制作tab切换 index.html ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <view class="swiper-tab&qu ...
 - Java对象创建的过程及对象的内存布局与访问定位
			
这里以HotSpot为例,且所说的对象指普通的Java对象,不包括数组和Class对象等. 1.对象创建的过程 1.类加载.解析.初始化:虚拟机遇到new时先检查此指令的参数是否能在常量池中找到类的符 ...
 - 使用python(command line)出现的ImportError: No module named 'xxx'问题
			
当你在python.exe直接输入 import test 时报出importerror: no module named 'test' ,这个错误时由于路径问题,sys并没有找到你输入的这个文件 解 ...
 - ubuntu 安装bazel
			
https://docs.bazel.build/versions/master/install-ubuntu.html#install-with-installer-ubuntu
 - OpenGL 用三角形模拟生成球面
			
在看OpenGL红皮书,看到生成球体这节,讲了很多,总感觉不如自己动手写一些代码来的实在,用OpenGL中三角形模拟球形生成.主要要点,模型视图变换,多边形表面环绕一致性,矩阵堆栈.先贴上代码. 虽然 ...
 - 分享:10 大顶级开源 ERP 系统
			
10 大顶级开源 ERP 系统 企业资源规划(ERP)和客户关系管理(CRM)系统现在已经成为各种组织和企业的必需品,通过它们,可以轻松实现企业的信息数据标准化.系统运行集成化.业务流程合理化.绩效监 ...
 - K-SVD算法
			
它与K-mean算法原理上是类似的: K-mean 算法: (之前写过:http://www.cnblogs.com/yinheyi/p/6132362.html) 对于初始化的类别中心,可以看作初化 ...
 - JDBC驱动程序类型
			
JDBC驱动程序是什么? JDBC驱动程序在JDBC API中实现定义的接口,用于与数据库服务器进行交互. 例如,使用JDBC驱动程序,可以通过发送SQL或数据库命令,然后使用Java接收结果来打开数 ...