Controller(控制器)在ASP.NET MVC中负责控制所有客户端与服务器的交互,并且负责协调Model和View之间的数据传递。
ASP.NET MVC的核心就是控制器(Controller),负责处理浏览器的所有要求,并决定响应什么属性给浏览器,但是Controller并不负责决定属性如何显示,仅响应特定的型态的属性给ASP.NET MVC框架,最后由ASP.NET MVC框架的View模块依据响应的型态来决定如何响应属性给浏览器。
撰写Controller的基本方法:
(1)Controller必须为公开方法;
(2)Controller名称必须以Controller结尾;
(3)必须继承自ASP.NET MVC内建的Controller类别,或者继承有实作IController界面的自定义类别,或者自行实作IController界面;
(4)所有动作方法必须为公开方法。任何非公开方法如声明为private或protected的方法都不会被视作一个动作方法。
当Controller被MvcHandler选中之后,下一步就是通过ActionInvoker选定适当的Action来运行。
Controller在运行时还有一层所谓的动作的过滤器(Action Filters)机制:第一,授权过滤器(Authorization Filters);第二,动作过滤器(Action Filters);第三,结果过滤器(Result Filters);第四,例外过滤器(Exception Filters)。容下面8中再讲......
(1)找不到Action时的处理方式
(2)动作名称选择器(Action Name Selector)
当通过ActionInvoker选定Controller内的公开方法时,默认会用Reflection的方式取得Controller中拥有action路由参数同名的方法(不区分英文大小写),这是默认行为。
如果在Action加上ActionName属性(Attribute)并指明为Default,此时,路由参数action的值就会变成必须是Default才会正确运行Index()这个动作方法,这就是动作名称选定器。这时需要注意的是,如果在Controller中使用默认的“return View();”回传ActionResult, 由于已经在动作方法上套用了ActionName("Default")属性,所以ASP.NET MVC会去寻找/Views/Home/Default.cshtml检视页面来运行,而不是/Views/Home/Index.cshtml。
如下就是访问/Views/Home/Index.cshtml的页面报错,因为此时程序中已经不存在Index动作方法。
如下就是访问/Views/Home/Default.cshtml的页面报错,程序中存在Default动作方法,但是不存在Default.cshtml文件。
当通过ActionInvoker选定Controller内的公开方法时,ASP.NET MVC还有另外一个特性称为“动作方法选定器”,同样可以套用在方法上,以便ActionInvoker“选定”适当的Action。
(1)NonAction属性
若套用NonAction属性在Controller里的Action方法上,即便该Action方法是“公开方法”,也会告知ActionInvoker不要选定这个Action开运行。
这个属性主要用途是用来保护Controller中特定的公开方法不要发布到Web上,或者是功能尚未开发完成就要进行部署,暂时不想将此方法删除就可以套用这个属性不要对外公开。或者直接将Action方法的public更改成private也可以达到同样的目的。
运行结果:
(2)HTTP动词限定属性
HttpGet、HttpPost、HttpDelete、HttpPut、HttpHead、HttpOptions、HttpPatch属性(Attributes)都是动作方法选定器的一份子。
1)动作方法上面没有套用动作限定属性的话,不管客户端浏览器发送任何HTTP动词都会自动选定对应的Action。
2)若动作方法上套用了HttpGet属性,即代表只有客户端浏览器发送HTTP GET要求时,ActionInvoker才会选定这个Action。
运行结果: 正常启动
运行结果:
3)这些属性最常用在需要接收窗体信息的时候。可以创建两个Action,一个套用HttpGet属性,以显示HTML,另一个属性套用HttpPost,以接收窗体输出的值。
///
/// 打开创建表单的页面
///
///
[HttpGet]
public ActionResult Create()
{
return View();
}
///
/// 提交创建的表单
///
///
///
[HttpPost]
public ActionResult Create(FormCollection c)
{
UpdateToDB(c);
return RedirectToAction("Index");
}
ActionResult是Acttion与运行后的回传型别,但是当Action回传ActionResult的时候,其实并不包含这个ActionResult的与运行结果,而是包含运行这个ActionRusult时所需的数据,当MvcHandler从Controller取得ActionResult之后,才会去运行出ActionResult的结果。ActionResult抽象类中仅定义了ExecuteResult()方法来运行结果:
(1)Controller辅助方法:ASP.NET MVC的Controller基类里面的辅助方法,这些辅助方法的主要目的是为了方便Controller中传回ActionResult相关型别之用。——使用更多
例如,转址到另一个页面,可用如下Controller辅助方法
(2)ActionResult的衍生型别:
1)ViewResult
ViewResult是在ASP.NET MVC中最常用的ActionResult,用于回传一个标准的验视(View)页面。
演示一:回传默认的验视页面
演示二:指定验视页面名称响应
演示三:指派的验视页面不存在---在Views对应的目录找不到AAA文件
从运行结果可以看出,为了在ASP.NET MVC中找到一个同名的View页面,尝试搜索了两个不同的扩展名,事实上这八个不同的路径分别由两个不同的验视引擎(ViewEngine)所支持,前四个是由WebFormViewEngine负责查找关联试图页面,后四个由RazorViewEngine负责查找关联视图页面。WebFormViewEngine默认支持的验视页面为MVC2以前常用的WebForm页面(*.aspx)和用户控件页面(*.ascx)。RazorViewEngine默认支持的验视页面为MVC3以后通常使用的Razor页面,在Razor页面里可支持C#语法(*cshtml)。
由此可知,ASP.NET MVC在查找View页面时默认第一顺序以WebFormViewEngine为主,第二顺序为RazorViewEngine。如果想要调正两个ViewEngine的搜索顺序,可以在Global.asax文档的Application_Start()方法中,添加一下代码:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//调整搜索目录的顺序
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
ViewEngines.Engines.Add(new WebFormViewEngine());
}
在搜索目录部分,ASP.NET MVC会到网站根目录下Views目录中搜索第一层目录,默认将会先搜索与Controller同名的目录,如果找不到对应的View页面,就会改为搜索Shared目录。指定验视页面名称与要套用的主版页面名称后,如下示例一:
示例二:
在HomeController的Read动作方法里,通过Model取得数据后将数据传至默认的验视页面中,这时ASP.NET MVC会尝试找出/View/Home/Read.cshtml验视页面,并传入model这个强类型队对象,最后将结果输出至客户端。
public ActionResult Read(int id)
{
Models.MvcGuestbookContext db = new Models.MvcGuestbookContext();
var model = from p in db.Messages where p.Id == id select p;
return View(model);
}
2)PartialViewResult
PartialViewResult与ViewResult非常类似,但无法为选中的View指派主版页面。
3)EmptyResult
有些Action不需要任何回传数据。
public ActionResult OnlineUserHit()
{
return new EmptyResult();
}
//或者,另一种表达
public ActionResult OnlineUserHit()
{
return;
}
4)ContentResult
响应任意“文字属性”的结果,可以任意指定文字属性、属性类型(Content-Type)与文字编码(Encoding)。
示例一:响应一段XML文字,设置响应的Content-Type为test/xml,并指定文字编码为Encoding.UTF-8
public ActionResult GetXML()
{
return Content("123 ","text/xml",System.Text.Encoding.UTF8);
}
示例二:只单纯的响应一串UTF-8编码的HTML字符串
public ActionResult GetHTML()
{
string strHTML = "...";//省略HTML的属性
return Content(strHTML);
}
还有另外一种表达,那就是直接将回传型设置成string即可。ASP.NET MVC会自动判断Action的回传类型,只要不是ActionResult的衍生类型,就会将回传的数据自动转换为ContentResult来输出。
///
/// 返回类型改为string型
///
///
public string GetHTML()
{
string strHTML = "...";//省略HTML的属性
return strHTML;
}
5)FileResult(包括FilePathResult、FileContentResult、FileStreamResult三种)
这三个类继承于FileResult,表示一个文件内容,三者区别在于,FilePath 通过路径传送文件到客户端,FileContent 通过二进制数据的方式,而FileStream 是通过Stream(流)的方式来传送。Controller为这三个文件结果类型提供了一个名为File的重载方法。
FilePathResult: 直接将一个文件发送给客户端
FileContentResult: 返回byte字节给客户端(比如图片)
FileStreamResult: 返回流
public ActionResult File()
{
string fileName = "~/Content/test.zip"; // 文件名
string downFileName = "文件显示名称.zip"; // 要在下载框显示的文件名
return File(fileName, "application/octet-stream", downFileName);
}
6)JavaScriptResult
用途是响应JavaScript程序代码给浏览器,通过ajax的程序开发,达到可以利用JavaScriptResult来响应适当的JavaScript程序代码让浏览器动态运行。
本质上是一个文本内容,只是将Response.ContentType设置为application/x-javascript,此结果应该和MicrosoftMvcAjax.js脚本配合使用,客户端接收到Ajax应答后,将判断Response.ContentType的值,如果是application/x-javascript,则直接eval 执行返回的应答内容,此结果类型对应得Controller方法为JavaScript.
7)JsonResult
表示一个Json结果。MVC将Response.ContentType 设置为application/json,并通过JavaScriptSerializer类指定对象序列化为Json表示方式。需要注意,默认情况下,Mvc不允许GET请求返回Json结果,要解除此限制,在生成JsonResult对象时,将其JsonRequestBehavior属性设置为JsonRequestBehavior.AllowGet,此结果对应Controller方法的Json。
8)RedirectResult
主要用途是运行重新导向到其他网址。
9)RedirectToRoute
10)HttpStatusCodeResult
主要用途是让ASP.NET MVC回传特定的HTTP状态代码与消息给客户端。
11)HttpNotFoundResult
专门用来响应HTTP404找不到网页的错误。
12)HttpUnauthorizedRusult
专门用来响应HTTP401拒绝访问的错误。
(10)
未完待续