了解ASP.NET MVC几种ActionResult的本质:EmptyResult & ContentResult2012-08-30 博客园 Artech定义在Controller中的Action方法大都返回一个ActionResult对象。ActionResult是对Action执行结果的封装,用于最终对请求进行响应。ASP.NET MVC提供了一系列的ActionResult,它们本质上是通过怎样的方式来响应请求的呢?这是这个系列着重讨论的主题。一、ActionResult对请求的响应HTTP是一个单纯的采用请求/回复消息交换模式的网络协议,Web服务器在接收并处理来自客户端的请求后会根据处理结果对请求予以响应。对于来自客户端的访问请求,最终的处理体现在针对目标Action方法的执行,我们可以在定义Action方法的时候人为地控制对请求的响应。如果下面的代码片断所示,抽象类Controller具有一个只读的Response属性表示当前的HttpResponse,我们可以直接利用它来实现对请求的响应。我们也可以间接地通过表示当前HTTP上下文的HttpContext属性和表示Controller上下文的ControllerContext属性来获取用于响应请求的HttpResponse对象。
 1: public abstract class Controller : ControllerBase, ...
 2: {
 3: //其他成员
 4: public HttpResponseBase Response { get; }
 5: public HttpContextBase HttpContext { get; }
 6: }
 7: 
 8: public abstract class ControllerBase : IController
 9: {
10: //其他成员
11: public ControllerContext ControllerContext { get; set; }
12: }
原则上讲,我们可以利用HttpResponse对请求响应作百分之一百地控制,但是我们一般并不这么做,而是将针对请求的响应实现在一个ActionResult对象中。如下面的代码片断所示,ActionResult是一个抽象类型,最终的请求响应实现在抽象方法ExecuteResult方法中。
 1: public abstract class ActionResult
 2: {
 3: //其他成员
 4: public abstract void ExecuteResult(ControllerContext context);
 5: }
顾名思义,ActionResult就是执行Action的结果。ActionInvoker在完成对Action方法的执行后,如果返回一个ActionResult对象,ActionInvoker会将当前Controller上下文作为参数调用其ExecuteResult方法。View的最终呈现是通过ActionResult的子类ViewResult来完成的,除了ViewResult,ASP.NET MVC还为我们定义了额外一些具体的ActionResult。二、EmptyResult上面我们谈到Action方法返回的ActionResult对象被ActionInvoker调用以实现对当前请求的响应,其实这种说法不够准确。不论Action方法是否具有返回值,也不论它的返回值是什么类型,ActionInvoker最终都会创建相应的ActionResult对象。如果Action方法返回类型为void,或者返回值为Null,最终生成的就是一个EmptyResult对象。如下面的代码片断所示,在重写的ExecuteResult方法中EmptyResult其实什么都没有做,所以EmptyResult是一个“空”的ActionResult。EmptyResult的设计体现了一种设计思想:我们采用一种管道式的设计来完成针对某类请求的处理,比如ASP.NET MVC针对请求的处理流程是“Action方法的执行=〉根据执行结果生成ActionResult=〉执行ActionResult”,但是这个流程不适合某些特殊的请求(比如Action方法不具有返回值或者返回值为Null,那么后面的两个环节可以忽略),我们对这些例外的场景进行一些适配工作使我们可以按照统一的方式来处理所有的请求,所以EmptyResult在这里起到了一个适配器的作用。
 1: public class EmptyResult : ActionResult
 2: {
 3: public override void ExecuteResult(ControllerContext context)
 4: {
 5: }
 6: }
三、ContentResultContentResult使ASP.NET MVC按照我们指定的内容对请求予以响应。如下面的代码片断所示,我们可以利用ContentResult的Content属性以字符串的形式指定响应的内容,另外两个属性ContentEncoding和ContentType则用于指定字符编码方式和媒体类型(MIME类型)。抽象类Controller定义了如下三个受保护的Content方法重载根据指定的内容、编码和媒体类型创建相应的ContentResult。
 1: public class ContentResult : ActionResult
 2: {
 3: public override void ExecuteResult(ControllerContext context);
 4:
 5: public string Content { get; set; }
 6: public Encoding ContentEncoding { get; set; }
 7: public string ContentType { get; set; }
 8: }
 9: 
10: public abstract class Controller : ControllerBase, ...
11: {
12: //其他成员
13: protected ContentResult Content(string content);
14: protected ContentResult Content(string content, string contentType);
15: protected virtual ContentResult Content(string content, string contentType, Encoding contentEncoding);
16: }