详解ASP.NET MVC 控制器
ASP.NET MVC系列文章
【02】浅谈Google Chrome浏览器(操作篇)(上)
【03】浅谈Google Chrome浏览器(操作篇)(下)
【04】浅谈ASP.NET框架
【07】浅谈ASP.NET MVC 路由
【08】浅谈ASP.NET MVC 视图
【10】浅谈jqGrid 在ASP.NET MVC中增删改查
【13】浅谈NuGet在VS中的运用
【14】浅谈ASP.NET 程序发布过程

1 概述
在阅读本篇博文时,建议结合上篇博文:详解ASP.NET MVC 路由 一起阅读,效果可能会更好些。
Controller(控制器)在ASP.NET MVC中负责控制所有客户端与服务端的交互,并且负责协调Model与View之间数据传递,是ASP.NET MVC框架核心。Controller为ASP.NET MVC框架的核心组成部分,其主要负责处理浏览器请求,并决定响应什么内容给浏览器,但并不负责决定内容应如何显示(View的职责)。
文章内容包括:Controller概述、Controller类别和方法、Controller运行过程、Controller方法类别、ViewData\ViewBag\TempData分析、ActionResult解说、Controller定义和参考文献,剩下有关Controller其他内容在本篇文章中不讲,如Controller激活机制(Controller类型解析、Controller类型缓存、Controller的释放和会话状态行为控制等)、ControllerFactory、ControllerBuilder等,除此之外,文中有些过于涉及到底层的内容,考虑篇幅等因素,只是简要提及了一下,并未做深入分析,根据后期情况,会酌情考虑是否再写一篇彻底深入的底层Controller的。
2 Controller类别和方法
Controller本身就是一个类(Class),该类别有许多方法(Method),这些方法中只要是公开方法(public method)就会被视为是一个动作(Action)或动作方法(Action Method),只要动作存在,就可以通过该动作方法接收客户端传来的要求与决定响应的检视(View)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace MVCControllerDemo.Controllers
{
public class ControllerDemoController : Controller
{
//
// GET: /ControllerDemo/ [HttpGet]
public ActionResult Index()
{
return View();
}
}
}
从如上代码可以总结出Controller应具备如下几个基本条件:
(1)Controller必须为公开类别;
(2)Controller名称必须以Controller结尾;
(3)必须继承自ASP.NET MVC内建的Controller类别,或实现IController自定义类别;
(4)所以动作方法必须为公开方法,任何非公开的方法如声明为private或protected的方法都不会被视为一个动作方法;
3 Controller的运行过程
当Controller被MvcHandler选中之后,下一步就是通过ActionInvoker选定适当的Action来运行。在Controllr中的每个Action可以定义0到多个参数,ActionInvoker会依据当下的RouteValue与客户端传来的数据准备好可传入Action参数的数据,最后正式调用Controller中被选中的那个Action方法。参数传入的属性都是通过一种称为模型绑定(Model Binding)机制,从RequestContext取得数据,并将数据对应或传入方法的参数中,让Action不用再像之前ASP或ASP.NET Web Forms中经常使用的Request.Fomr或Request.QueryString等对象来取得客户端的数据,通过自定义的模型绑定,甚至可以让你对应除了Request.Form或Request.QueryString以外的数据来源,例如:HTTP Cookies、HTTP Headers等等。
Action运行完后的回传值通常是ActionResult类别或其衍生类别(Derived Class),事实上,ActionResult是一个抽象类,如ViewResult用来回传一个View、RedirectResult用来将网页重定向、Content回传文字内容、FileResult回传二进制文档等,这些均是继承ActionResult。MvcHandler从Controller得到ActionResult之后,就会开始运行ActionResult提供的ExecuteResult方法,并将运行结果响应到客户端,这时Controller的任务就算完成。
以上为Controller的基本运行过程。Controller在运行时还有一层所谓的动作过滤器机制,分为如下四种基本类型:
(1)授权过滤器(Authorization Filters);
(2)动作过滤器(Action Filters);
(3)结果过滤器(Result Filters);
(4)例外过滤器(Exception Fiters);
4 控制器方法类别
4.1 动作方法选定器
当通过ActionInvoker选定Controller内的公开方法时,ASP.NET MVC还有另一个特性称为"动作方法选定器(Action Method Selector)",该选定器可以套用在动作方法上,以便ActionInvoker"选定"适当的Action。
(1)NonAction属性
若控制器某个方法特性为NonAction,即使该Action方法是“公开方法”,也会告知ActionInvoker不要选定这个Action来运行。主要用途:a.保护Controller中的特定公开方法不要发布到Web上;b.功能尚未开发完成就要进行部署,暂时不想将此方法删除。
[NonAction]
public ActionResult Index()
{
return View();
}
也可将public改为private,达到保护的效果。
private ActionResult Index()
{
return View();
}
(2)HTTP动词限定属性
HttpGet、HttpPost、HttpDelete、HttpPut、HttpHead、HttpOptions、HttpPatch属性(Attributes)都是动作方法选定器的一部分。如下例子讲解HttpGet属性,即代表只有当客户端浏览器发送HTTP GET要求时,ActionInvoker才会选定到这个Action:
[HttpGet]
public ActionResult Index()
{
return View();
}
若将[HttpGet]改为[HttpPost],浏览器将找不到资源。
[HttPost]
public ActionResult Index()
{
return View();
}

注释:如果动作方法上没有嵌套任何限定属性,那么客户端浏览器发送任意HTTP动词都会自动选定到对应的Action。
当需要显示接收窗体信息时,可以创建两个同名的Action,分别用[HttpGet](显示窗体HTML)和[HttpPost](接收窗体输出的值)属性来限定。
[HttpGet]
public ActionResult Index()
{
return View();
} [HttpGet]
public ActionResult Create()
{
return View();
} [HttpPost]
public ActionResult Create(FormCollection fc)
{
//UpdateToDB(fc);
return RedirectToAction("Index");
}
4.2 操作过滤器
一个操作方法一旦被选中就会立即执行,并且如果它返回一个结果,返回的结果也会随后执行,ASP.NET MVC 5提供五种方式,分别列于如下:
- 即身份验证
- 授权
- 操作前后处理
- 结果前后处理
- 错误处理。
除此之外,还有另外一种过滤器,即重写过滤器,它允许为全局或控制器的默认集合制定例外情况。
操作过滤器可以作为直接运用于操作方法或控制器类的特性来编写,或作为在全局过滤器列表中注册的单独类来编写。如果打算将编写的操作过滤器作为特性来使用,那么它必须继承自FilterAttribute或它的任何子类,如ActionFilterAttribute。不作为特性使用的全局操作过滤器没有对这个基类的要求。无论采用哪个路由,操作过滤器支持的过滤活动都由实现的接口决定。
5 Controller动作结果
5.1 控制器动作结果类型(ActionResult)
通常,在定义一个方法时,我们常规性地根据方法是否有返回值归结为有返回值和无返回值两大类,控制器的本质是类,控制器的action本质是方法,如果按照数学集合来定义,那么控制器是类的一个子集,同理,控制器action是方法的一个子集,因此,在研究控制器以及控制器action时,我们是可以才用研究类和方法的一般思维的。
控制器动作(具体的action)返回的结果叫做控制器动作结果,动作结果是控制器返回给浏览器请求的内容。ASP.NET MVC框架支持六种标准类型的动作结果。
(1)继承ActionResult的动作结果

(2)继承关系

(3)例子
eg1:ViewResult
//方法1: ViewResult作为返回类型
public ViewResult Index()
{
return View();
} //方法二: ViewResultBase作为返回类型
public ViewResultBase Index()
{
return View();
} //方法三: ActionResult作为返回类型
public ActionResult Index()
{
return View();
}
eg2:EmptyResult
// GET: /ControllerDemo/
public EmptyResult Index()
{
return null;
}
eg3:ContentResult
//方法1:ContentResult作为返回类型
public ContentResult Index()
{
return Content("Hello World");
} //方法2:ActionResult作为返回类型
public ActionResult Index()
{
return Content("Hello World");
}
eg4:JsonResult
public JsonResult jsonResult()
{
TechInfoCompanay jsonCompany=new TechInfoCompanay(){id="S001",CompanyName="信息科技有限公司"};
return Json(jsonCompany,JsonRequestBehavior.AllowGet);
} //定义一个公司类
public class TechInfoCompanay
{
public string id { set; get; }
public string CompanyName { set; get; }
}
eg5:RedirectResult
//方法1:RedirectResult作返回类型
public RedirectResult redirectResult()
{
return Redirect("https://www.google.com.hk/");//具体的URL
} //方法1: ActionResult作返回类型
public ActionResult redirectResult()
{
return Redirect("https://www.google.com.hk/");//具体的URL
}
eg6:RedirectToRouteResult
public ActionResult redirectResult()
{
return Redirect("https://www.google.com.hk/");//具体的URL
} public RedirectToRouteResult redirectToRouteResult()
{
return RedirectToAction("Index");
}
5.2一般方法
(1)如下只是给出方法样式,不做具体代码。
//无返回类型
public void functionName(形参)
{
//to add your content
} //有返回类型
public 返回类型 functionName(形参)
{
//to add your content
return 与方法返回类型相匹配的结果;
}
(2)例子
eg:举个自定义返回string的方法
RouteConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing; namespace MVCControllerDemo
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { Controller = "ControllerDemo", action = "Index", id = UrlParameter.Optional }
);
}
}
}
ControllerDemoController.action
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace MVCControllerDemo.Controllers
{
public class ControllerDemoController : Controller
{ public string GeneralFunction()
{
return "自定义一般方法";
}
}
}
测试结果

6 ViewBag、ViewData和TempData概述
6.1 三者在MVC框架里的定义
在MVC框架中,System.Web.Mvc命名空间下的ControllerBase中,对ViewBag、ViewData和TempData三个属性的定义如下
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;
}
}
ViewData
public ViewDataDictionary ViewData
{
get
{
if (this._viewDataDictionary == null)
{
this._viewDataDictionary = new ViewDataDictionary();
}
return this._viewDataDictionary;
}
set
{
this._viewDataDictionary = value;
}
}
TempData
public TempDataDictionary TempData
{
get
{
if ((this.ControllerContext != null) && this.ControllerContext.IsChildAction)
{
return this.ControllerContext.ParentActionViewContext.TempData;
}
if (this._tempDataDictionary == null)
{
this._tempDataDictionary = new TempDataDictionary();
}
return this._tempDataDictionary;
}
set
{
this._tempDataDictionary = value;
}
}
6.2 三者比较
(1)ViewData和TempData属性均返回一个具有字典结构的数据容器,即字典类型的key/Value对,ViewBag为Dynamic类型。
三者方法签名为:
public TempDataDictionary TempData { get; set; }
public ViewDataDictionary ViewData { get; set; }
3 public object ViewBag { [return: Dynamic] get; }
(2)TempData存储临时数据,并且设置的变量在被第一次读取后会被移除,即TempData设置的变量只能被读取一次。(why?)
(3)ViewBag和ViewData属性是同一份数据的不同表现形式,二者的不同之处在于前者是一个动态对象,可以为其指定任意属性(动态属性名将作为数据字典的Key)。
(4)三者均是容器,即能存储常量,变量,也能存储集合。
7 ActionResult解说
在ASP.NET MVC框架中,对ActionResult定义如下:
// Generated by .NET Reflector from C:\Users\WJM\documents\visual studio 2013\Projects\DEMOMVC\packages\Microsoft.AspNet.Mvc.5.0.0\lib\net45\System.Web.Mvc.dll
namespace System.Web.Mvc
{
using System; public abstract class ActionResult
{
protected ActionResult()
{
} public abstract void ExecuteResult(ControllerContext context);
}
}
ActionResult是Action运行后的回传型别,但是当Action回传ActionResult的时候,其实并不包含这个ActionResult(例如ViewResult)的运行结果,而是包含运行这个ActionResult时所需的数据,当MvcHandler从Controller取得ActionResult之后才会去运行出ActionResult的结果。在ActionResult抽象类中仅仅定义了一个ExecuteResult()方法。
ASP.NET 定义了以下几种衍生型别。

8 控制器定义
一般地,在定义Controller时,采用两种方式,即实现IController和继承Controller。
8.1 实现IController
RouteConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing; namespace MVCControllerDemo
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { Controller = "ControllerDemo", action = "Index", id = UrlParameter.Optional }
);
}
}
}
RouteDemoController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; using System.Reflection;
namespace MVCControllerDemo.Controllers
{
public class ControllerDemoController : IController
{
public String Index()
{
return "<h1>Index</h1>";
} public void Execute(System.Web.Routing.RequestContext requestContext)
{
string action = requestContext.RouteData.Values["action"].ToString();
Type typ = typeof(ControllerDemoController);
MethodInfo md = typ.GetMethod(action, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (md == null)
{
requestContext.HttpContext.Response.Write("<h1>404</h1>");
}
else
{
string s = md.Invoke(this, null).ToString();
requestContext.HttpContext.Response.Write(s);
}
}
}
}
8.2 继承Controller
这种方法比较常用。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace MVCControllerDemo.Controllers
{
public class ControllerDemoController : Controller
{
//
// GET: /ControllerDemo/ [HttpGet]
public ActionResult Index()
{
return View();
}
}
}
9 参考文献
【01】http://www.cnblogs.com/wangiqngpei557/p/3390812.html
【02】http://www.cnblogs.com/yaozhenfa/p/asp_net_mvc_controller.html
【03】http://www.360doc.com/content/12/0611/15/29831_217456312.shtml
【04】http://blog.csdn.net/yw1688/article/details/51280665
【05】Professional Asp.net MVC 5
【06】Professional Asp.net MVC 4
【07】The framework of revelation of Professional Asp.net MVC 5
【08】 https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/aspnet-mvc-controllers-overview-cs
10 版权
- 感谢您的阅读,若有不足之处,欢迎指教,共同学习、共同进步。
- 博主网址:http://www.cnblogs.com/wangjiming/。
- 极少部分文章利用读书、参考、引用、抄袭、复制和粘贴等多种方式整合而成的,大部分为原创。
- 如您喜欢,麻烦推荐一下;如您有新想法,欢迎提出,邮箱:2016177728@qq.com。
- 可以转载该博客,但必须著名博客来源。
详解ASP.NET MVC 控制器的更多相关文章
- 详解ASP.NET MVC的请求生命周期
本文的目的旨在详细描述asp.net mvc请求从开始到结束的每一个过程. 我希望能理解在浏览器输入url并敲击回车来请求一个asp.net mvc网站的页面之后发生的任何事情. 为什么需要关心这些? ...
- 详解ASP.NET MVC应用程序请求生命周期
------转载当一个ASP.NET MVC应用程序提出请求,为了响应请求,包含一些请求执行流程步骤! 在ASP.NET MVC应用程序Http request 和Http response 过程中, ...
- jquery.uploadify上传文件配置详解(asp.net mvc)
页面源码: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" c ...
- 详解Asp.net MVC DropDownLists
Asp.net MVC中的DropDownLists貌似会让一开始从Asp.net Forms转过来的程序员造成不少迷惑.这篇文章讲述了为了使用DropDownLists,你需要在Asp.Net MV ...
- 详解ASP.NET MVC Model验证
ASP.NET mvc的最好的优点之一就是支持Model验证,这个特性很方便你可以选择在定义Model的时候在字段中采用特性进行注解约定,也可以在代码中自己进行手动验证.下面就来细说一下ASP.NET ...
- 【ASP.NET MVC系列】浅谈ASP.NET MVC 控制器
ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...
- 【半小时大话.net依赖注入】(下)详解AutoFac+实战Mvc、Api以及.NET Core的依赖注入
系列目录 上|理论基础+实战控制台程序实现AutoFac注入 下|详解AutoFac+实战Mvc.Api以及.NET Core的依赖注入 前言 本来计划是五篇文章的,每章发个半小时随便翻翻就能懂,但是 ...
- 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射
使用Code First建模自引用关系笔记 原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasR ...
- ASP.NET MVC 控制器激活(一)
ASP.NET MVC 控制器激活(一) 前言 在路由的篇章中讲解了路由的作用,讲着讲着就到了控制器部分了,从本篇开始来讲解MVC中的控制器,控制器是怎么来的?MVC框架对它做了什么?以及前面有的篇幅 ...
随机推荐
- Kotlin学习第一课:从对比Java开始
1. 介绍 今年初,甲骨文再次对谷歌所谓的安卓侵权使用Java提起诉讼,要求后者赔偿高达90亿美元.随后便传出谷歌因此计划将主力语言切换到苹果主导的Swift,不过这事后来没了跟进. 但谷歌在这两天的 ...
- OpenCV探索之路(十一):轮廓查找和多边形包围轮廓
Canny一类的边缘检测算法可以根据像素之间的差异,检测出轮廓边界的像素,但它没有将轮廓作为一个整体.所以要将轮廓提起出来,就必须将这些边缘像素组装成轮廓. OpenCV中有一个很强大的函数,它可以从 ...
- struts2.1.6教程九、文件上传下载(了解)
首先建立struts2UpDownLoad项目,搭建好struts2基本的开发环境. 上传实例 步骤一:upload.jsp代码如下: <s:form action="upload&q ...
- 深入理解C#中的String
关于C#中的类型 在C#中类型分为值类型和引用类型,引用类型和值类型都继承自System.Object类,几乎所有的引用类型都直接从System.Object继承,而值类型具体一点则继承System. ...
- R语言进行文件夹操作示例(转)
rm(list=ls())path = 'J:/lab/EX29 --在R语言中进行文件(夹)操作'setwd(path)cat("file A\n", file="A& ...
- cas4.2.7实现单点登录
准备前参考: cas server下载地址 cas client 下载地址 安全cookie setSecure详解 Spring通过构造方法注入的四种方式 cas 学习博文 自定义登录页和登录认证 ...
- VR全景:电商巨头的角逐
VR全景智慧城市:京东推"京东梦"挑战淘宝Buy+ ,VR购物谁主沉浮? VR全景智慧城市是国内首家商业全景平台,结合先进VR虚拟现实技术,以线下实体为依托,将空间还原到线上,用户 ...
- OpenGL教程(1)——准备
在正式开始学习OpenGL之前,我们需要先配置好OpenGL环境. IDE 首先我们需要选择一个IDE.支持OpenGL的IDE有很多,这里我们选择Visual Studio 2015(Windows ...
- java(3) if结构
一.基本if结构 1.流程图 1)输入输出 2)判断和分支 3) 流程线 1.1 简单的if条件判断 if(表达式){ //表达式为true,执行{}中的代码 } 示例1:如 ...
- Python 操作 Azure Blob Storage
笔者在<Azure 基础:Blob Storage>一文中介绍了 Azure Blob Storage 的基本概念,并通过 C# 代码展示了如何进行基本的操作.最近笔者需要在 Linux ...