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 (二)控制器的更多相关文章

  1. ASP.NET MVC 视图(二)

    ASP.NET MVC 视图(二) 前言 上篇中对于视图引擎只是做了简单的演示,对于真正的理解视图引擎的工作过程可能还有点模糊,本篇将会对由MVC框架提供给我们的Razor视图引擎的整个执行过程做一个 ...

  2. ASP.NET MVC学习之控制器篇扩展性

    原文:ASP.NET MVC学习之控制器篇扩展性 一.前言 在之前的一篇随笔中已经讲述过控制器,而今天的随笔是作为之前的扩展. 二.正文 1.自定义动作方法 相信大家在开发过程一定会遇到动作方法的重名 ...

  3. ASP.NET MVC 5 04 - 控制器

    PS: 唉.本来这一篇前几天早就应该发了的,可是谁每月没有那么几天啊... 呵呵.开个玩笑.反正就是各种烦气,所以也就一直没上来继续发了. 年底了,摆正一下心态吧.好好干,整点钱,过年回家能跟亲朋好友 ...

  4. ASP.NET MVC 路由(二)

     ASP.NET MVC路由(二) 前言 在上一篇中,提及了Route.RouteCollection对象的一些信息,以及它们的结构所对应的关系.按照处理流程走下来还有遗留的疑问没有解决这个篇幅就来讲 ...

  5. ASP.NET MVC 5 -从控制器访问数据模型

    在本节中,您将创建一个新的MoviesController类,并在这个Controller类里编写代码来取得电影数据,并使用视图模板将数据展示在浏览器里. 在开始下一步前,先Build一下应用程序(生 ...

  6. asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析

    下面我用一个实例来和大家分享一下我的经验,asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析. using Newtonsoft.Json; usin ...

  7. 【ASP.NET MVC系列】浅谈ASP.NET MVC 视图与控制器传递数据

    ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...

  8. [转]ASP.NET MVC 5 -从控制器访问数据模型

    在本节中,您将创建一个新的MoviesController类,并在这个Controller类里编写代码来取得电影数据,并使用视图模板将数据展示在浏览器里. 在开始下一步前,先Build一下应用程序(生 ...

  9. ASP.NET MVC学习之控制器篇(二)

    原文链接:http://www.asp.net/learn/mvc/ 这篇教程探索了ASP.NET MVC控制器(controller).控制器动作(controller action)和动作结果(a ...

随机推荐

  1. TiKV 源码解析系列——如何使用 Raft

    本系列文章主要面向 TiKV 社区开发者,重点介绍 TiKV 的系统架构,源码结构,流程解析.目的是使得开发者阅读之后,能对 TiKV 项目有一个初步了解,更好的参与进入 TiKV 的开发中. 需要注 ...

  2. js关于弹也遮罩层

    1:什么是遮罩层 遮罩层:我是弹也一个(遮罩层)还有一个(内容层),下面上图片看一效果 我们看到一个灰蒙蒙的遮盖(其实也是一个层)还有一个层(也就是我们展示的内容). 2:  弹出层效果居中分析 在这 ...

  3. 安卓程序代写 网上程序代写[原]BluetoothDevice详解

    一. BluetoothDevice简介 1. 继承关系 public static Class BluetoothDevice extends Object implement Parcelable ...

  4. WPF Tutorial - Using A Visual Collection

    While WPF and XAML make the common 90% of UI programming quite easy, sometimes it gets a little odd ...

  5. Check which .NET Framework version is installed

    his article will help you to know which .NET Framework version is installed from command line. Check ...

  6. I2C上拉电阻

    在一些PCB的layout中,大家往往会看到在I2C通信的接口处,往往会接入一个4.7K的电阻,有的datasheet上面明确有要求,需要接入,有的则没有要求.   I2C接口 对于单片机来讲,有些I ...

  7. C艹复合类型(字符串)

    在C艹中有两种字符串形式, 一种是C-风格, 另一种是C艹风格的 初始化: char str[10] = {'a', 'c', 'd', '\0'};char str[20]= “aaa”; stri ...

  8. 成功安装vscode中go的相关插件

    让你成功安装vscode中go的相关插件 注意:该演示环境是windows环境,linux和mac环境操作思路一样 vscode中有很多go的相关插件,非常好用如下:gocodegopkgsgo-ou ...

  9. llinux 环境安装编译 nginx (源码安装包)

    简介: Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行.由俄罗斯的程序设计师Igor Sysoev所开发,供俄国 ...

  10. glsl boom

    原理: 1.渲染场景到fbo 2.对fbo进行高斯横向,纵向模糊,到新的fbo 3.对两张图进行叠加 模糊后的 效果就这样 给数据加大 <-vertex-> #version varyin ...