一、         ASP.NET MVC 1.0 Result 几何?

Action的返回值类型到底有几个?咱们来数数看。

ASP.NET MVC 1.0 目前一共提供了以下十几种Action返回结果类型:

1.       ActionResult(base)

2.       ContentResult

3.       EmptyResult

4.       HttpUnauthorizedResult

5.       JavaScriptResult

6.       JsonResult

7.       FileResult (base)

8.       FileContentResult

9.       FilePathResult

10.   FileStreamResult

11.   RedirectResult

12.   RedirectToRouteResult

13.   ViewResultBase(base)

14.   ViewResult

15.   PartialViewResult

一个列表下来看得人眼花缭乱,因为可用的Result很多,接着再瞧瞧类关系图以佐辨析:

<图>

如图中可见,ActionResult可谓人丁兴旺,目前膝下有儿9子(如图中红色所圈的类),ViewResultBase与FileResult又各有子两三口,这些儿孙们各司所长。那么各个 Result 都会干点啥事儿呢?这个问题说来话长,不过根据诸如“虎父无犬子”、“种瓜得瓜,种豆得豆”、“龙生龙,凤生凤,老鼠的孩子打地洞”的俗语,孩子们多少从他爹那儿遗传了点什么,所以要说明它们的才干之前,得先唠叨唠叨一下 ActionResult这个爹,这个爷,因此这事情还是得先从ActionResult说起。

二、朴实的 ActionResult

所有的 Result 都派生自 ActionResult抽象类,因此 ActionResult 作为基类提供了最基础的功能,ActionResult 是一个抽象类,其声明如下:

public abstract class ActionResult {

public abstract void ExecuteResult(ControllerContext context);

}

看看普通人民、相貌平平的ActionResult,ActionResult 是个朴素老百姓,没啥特长,就一个 ExecuteResult()抽象方法,这个ExecuteResult() 抽象方法还啥都不干,遗传给儿女孙子们让它们去发挥,那么它的责任其实就很明确了,它就是为遗传作准备的,繁殖下一代用的,是只公猪种。因为ActionResult是所有Result的基类,因此你可以在所有的Action上使用它作为返回值类型,而无需动脑筋来明确与返回值相同的类型。

二、         EmptyResult

EmptyResult 是ActionResult 最没用的儿子,虽然生儿都想生孙仲谋,希望儿子们都是八斗之才,国家栋梁,可惜第一胎 EmptyResult 就严重破坏了它的梦想,看来也只能痛恨自己种子不够好。咱来瞧瞧这个没用的阿斗:

//表示一个啥都不干的结果,就像 controller action 返回 null

public class EmptyResult : ActionResult {

private static readonly EmptyResult _singleton = new EmptyResult();

internal static EmptyResult Instance {

get {

return _singleton;

}

}

public override void ExecuteResult(ControllerContext context) {

}

}

EmptyResult 遗传并实现了ActionResult的ExecuteResult()方法,同时也遗传了ActionResult的天真朴实的想法,也想“还是等下一代吧”,它有点老子的“无为”味道,所以它的ExecuteResult()方法像足了它的老爹,啥也不干。

EmptyResult 类使用了简单的单例模式,看来这样不思进取的儿子,整个家族里头生一个就够糟糕了,用广东人的话说,生它还不如生块叉烧肉。

在Action中,若要返回一个空的页面(不常用),则可如下:

public ActionResult Index()

{

return new EmptyResult();

}

执行后页面将缺省返回一个body为空的HMTL架构:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head>
<meta content="text/html; charset=gb2312" http-equiv=content-type></head>
<body></body></html>

三、RedirectResult

EmptyResult的“无为”给ActionResult 的打击着实不小,只好将期待落在其他孩子身上,RedirectResult虽然不是什么大才,起码有一技之长,我们看看它的 ExecuteResult() 方法:

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

}

string destinationUrl = UrlHelper.Content(Url, context.HttpContext);

context.HttpContext.Response.Redirect(destinationUrl, false /* endResponse */);

}

RedirectResult用于执行转移。事实上 RedirectResult 最终调用了 Response.Redirect() 进行转移,所以您可以使用RedirectResult跳转到任意的包括当前项目或网络上的Url,例如:http://www.cnblogs.com,对于当前项目的路径,因为使用了UrlHelper.Content() 方法获取目标路径,所以RedirectResult传递的Url同时支持当前项目目录标识符 ~ (即应用程序目录)。

四、RedirectToRouteResult

RedirectToRouteResult对于RedirectResult而言,其作用有所局限,仅能转移到路由(路由匹配的结果最终是一条相对当前项目的Url,例如: /Home/Index ),总的来说与RedirectResult的最终作用是一样的,都是执行转移。RedirectResult较为直接地转移到任意指定的Url,而RedirectToRouteResult则转移到指定的路由(路由匹配所得结果最终也是一个的Url):

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

}

string destinationUrl = UrlHelper.GenerateUrl(RouteName, null /* actionName */,null /* controllerName */, RouteValues, Routes, context.RequestContext, false /* includeImplicitMvcValues */);

if (String.IsNullOrEmpty(destinationUrl)) {

throw newInvalidOperationException(MvcResources.ActionRedirectResult_NoRouteMatched);

}

context.HttpContext.Response.Redirect(destinationUrl, false /* endResponse */);

}

RedirectToRouteResult先通过调用UrlHelper.GenerateUrl()来获得路由匹配所得的最终Url,接着的执行转移过程与RedirectResult相同。

路由配置的过程在Global.asax文件中进行,在以MVC模板方式创建的MVC项目中都带有此文件,可在文件中的MvcApplication类的RegisterRoutes()方法中进行配置路由,该方法缺省的内容如下:

public static void RegisterRoutes( RouteCollection routes )

{

routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" );

routes.MapRoute(

"Default",                                              // Route name

"{controller}/{action}/{id}",                           // URL with parameters

new { controller = "Home", action = "Index", id = "" } // Parameter defaults

);

}

RedirectToRouteResult 可跳转至任何一条匹配的路由规则。是以利用路由转移可以跳转到其他控制器的 Action。

五、ContentResult

ContentResult用于将字符串直接向客户端输出。ContentResult的ExecuteResult方法实际上是调用了 Response.Write( string… ),输入并无特别之处,但是在 ASP 时代,这个Response.Write() 却是可以纵横页面。从输出一个简单的字符串到整个页面,Response.Write()都能胜任,所以ContentResult显得特别强大:

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

}

HttpResponseBase response = context.HttpContext.Response;

if (!String.IsNullOrEmpty(ContentType)) {

response.ContentType = ContentType;

}

if (ContentEncoding != null) {

response.ContentEncoding = ContentEncoding;

}

if (Content != null) {

response.Write(Content);

}

}

若没有提供任何输出的内容,ContentResult呈现的结果与EmptyResult 是一样的,都是输出最基本的<body>标记内容为空的HTML,若内容不为空,则直接输出这些内容(不再输出其他任何 HTML 代码),例如:

public ActionResult Index()

{

return Content( "a" );

}

其页面的HTML代码也将只有一个字符 a,要补全所有基本标记需要在字符串中编写,例如:

public ActionResult Index()

{

return Content( "<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN"">" +

"<html>" +

"<head><meta content=""text/html; charset=gb2312"" http-equiv=content-type></head>" +

"<body>" +

"abc" +

"</body>" +

"</html>"

);

}

当然不建议使用此方法来输出页面标记,ContentResult 用在Ajax中颇为合适,因为只要内容不为空,输出的字符串与传送到客户端的内容一致,没有额外的附加内容。

事实上从ContentResult我们可以看到一个ActionResult其实并无特别,从前面几个Result 来看,其实不过是Response.Redirect或Response.Write,此外还可以利用二进制流Response.OutputStream.Write向客户端上载文件……据此我们所以拓展编写更多针对实际意义的Result。例如 XmlResult(文件)、RssResult(跟XmlResult其实是一样的)等等。

六、JsonResult

JsonResult首先将指定的对象序列化为Json字符串,然后将字符串写入到HTTP输出流。撇开对象序列化为Json字符串这一过程,实际上与ContentResult其实是一样的,因为JsonResult与ContentResult都是调用Response.Write()向HTTP输出流写入一些内容。所以对此不再赘述:

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

}

HttpResponseBase response = context.HttpContext.Response;

if (!String.IsNullOrEmpty(ContentType)) {

response.ContentType = ContentType;

}

else {

response.ContentType = "application/json";

}

if (ContentEncoding != null) {

response.ContentEncoding = ContentEncoding;

}

if (Data != null) {

// The JavaScriptSerializer type was marked as obsolete prior to .NET Framework 3.5 SP1

#pragma warning disable 0618

JavaScriptSerializer serializer = new JavaScriptSerializer();

response.Write(serializer.Serialize(Data));

#pragma warning restore 0618

}

}

有个地方想唠叨两句,在代码中的:

response.ContentType = "application/json";

若要直接向页面输出的话需要更改为文本类型,例如 text/html,否则你要以文件形式下载JsonResult的结果内容。不过这对于将Json用于Ajax而言不会有什么影响。

七、JavaScriptResult

道与 JsonResult、ContentResult相同。所以也不赘述,徒费唇舌:

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

}

HttpResponseBase response = context.HttpContext.Response;

response.ContentType = "application/x-javascript";

if (Script != null) {

response.Write(Script);

}

}

八、HttpUnauthorizedResult

HttpUnauthorizeResult 设置客户端错误代号为 401,即未经授权浏览状态,若设置了Form验证并且客户端没有任何身份票据,那么将转跳到指定的页面(例如登陆页):

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

}

// 401 is the HTTP status code for unauthorized access - setting this

// will cause the active authentication module to execute its default

// unauthorized handler

context.HttpContext.Response.StatusCode = 401;

}

可以学习HttpUnauthorizeResult来编写更多同类的返回结果,例如设置 Response.StatusCode = 404,这个是常见的“页面未找到”错误,403 禁止访问等等。

九、FileResult

FileResult是一个抽象类,主要属性包括声明内容类型信息ContentType 及文件名称FileDownloadName,客户端下载工具中将显示此名称(如果有指定,ContentType可指定任意非空字符串),如果不指定文件名,ContentType需要正确指定,否则无法识别待下载的文件类型。

FileResult 用作其他向客户端上载文件的类的基类。

十、FilePathResult

FilePathResult 继承自 FileResult,使用 FilePathResult 类向客户端上载文件只需要给出文件的路径即可。FilePathResult 将调用 Response.TransmitFile() 传输该文件:

protected override void WriteFile(HttpResponseBase response) {

response.TransmitFile(FileName);

}

十一、FileContentResult

FileContentResult继承自 FileResult。

FileContentResult 将指定的字节内容写入二进制流(客户端将以文件形式下载),对比 FilePathResult 所不同的是 FilePathResult是给出文件路径,然后将整份文件上载给客户,而 FileContentResult 则可以传输某一个字节数组,例如:

public ActionResult Index()

{

return File( System.Text.Encoding.UTF8.GetBytes( "你好吗" ), "unknown", "t.txt" );

}

FileContentResult 使用 Response.OutputStream.Write 输出内容:

protected override void WriteFile(HttpResponseBase response) {

response.OutputStream.Write(FileContents, 0, FileContents.Length);

}

十二、FileStreamResult

FileStreamResult 继承自 FileResult。

FileStreamResult 向指定文件流读取数据,其他的内容与FileContentResult道同。请参考FileContentResult。

MVC Action 返回类型[转]的更多相关文章

  1. MVC Action 返回类型

    https://www.cnblogs.com/xielong/p/5940535.html https://blog.csdn.net/WuLex/article/details/79008515 ...

  2. asp.net mvc 3.0 知识点整理 ----- (2).Controller中几种Action返回类型对比

    通过学习,我们可以发现,在Controller中提供了很多不同的Action返回类型.那么具体他们是有什么作用呢?它们的用法和区别是什么呢?通过资料书上的介绍和网上资料的查询,这里就来给大家列举和大致 ...

  3. MVC3中Action返回类型ActionResult类型

    MVC3中Action返回类型ActionResult在System.Web.Mvc命名空间中.这些包含在控制器中的方法,我们称为控制器中的 Action,比如:HomeController 中的 I ...

  4. ASP.NET MVC Action返回结果类型【转】

    ASP.NET MVC 目前一共提供了以下几种Action返回结果类型: 1.ActionResult(base) 2.ContentResult 3.EmptyResult 4.HttpUnauth ...

  5. Spring MVC之Action返回类型

    Spring MVC支持的方法返回类型 1)ModelAndView 对象.包含Model和View对象,可以通过它访问@ModelAttribute注解的对象. 2)Model 对象.仅包含数据访问 ...

  6. Asp.Net MVC 利用ReflectedActionDescriptor判断Action返回类型

    System.Web.Mvc.ReflectedActionDescriptor descriptor = filterContext.ActionDescriptor as System.Web.M ...

  7. Spring MVC Action参数类型 List集合类型(简单案例)

    题目:定义一个员工实体(Employee),实现批量添加员工功能,在表单中可以一次添加多个员工,数据可以不持久化 1,新建一个项目 2, 然后选择Maven框架选择 maven-archetype-w ...

  8. Action返回类型

    1.返回ascx页面return PartialView(); 2.Content(),返回文本ContentResultreturn Content("这是一段文本"); 3.J ...

  9. ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)

    要啥自行车,直接看手表 //返回基元类型 public string Get() { return "hello world"; } //返回复杂类型 public Person ...

随机推荐

  1. [翻译][MVC 5 + EF 6] 9:异步和存储过程

    原文:Async and Stored Procedures with the Entity Framework in an ASP.NET MVC Application 1.为什么使用异步代码: ...

  2. 【HeadFirst设计模式】7.适配器模式与外观模式

    今晚学习完第七章,顺便做一下知识备忘. 适配器模模式: 定义:将一个类的接口,转换成客户期望的另一个接口.适配器让原本接口不兼容的类可以合作无间. 对象适配器: 类适配器: 外观模式: 提供了一个统一 ...

  3. 基于bootstrap3的 表格和分页的插件

    如题 样式呢就是bootstrap3 的 功能呢就是实现表格和分页 (以上废话) 本来是自己没事儿写的一个js插件,曾经搁浅了一阵子,但最近由于公司项目的原因也需要这样的一个插件,所以就捡起来做了个可 ...

  4. jquery垂直公告滚动实现代码

    公告滚动想必大家都有见到过吧,实现方法也有很多,下面为大家介绍使用jquery实现垂直公告滚动,感兴趣的朋友不要错过 复制代码代码如下: <!DOCTYPE html PUBLIC " ...

  5. 004.CleanUp方法

    定义: Delphi procedure CleanUp; 类型 可见性 所在源码 所在单元 父类 procedure protected System.RegularExpressionsCore. ...

  6. 8.MVC框架开发(URL路由配置和URL路由传参空值处理)

    1.ASP.NET和MVC的路由请求处理 1)ASP.NET的处理 请求---------响应请求(HttpModule)--------处理请求(HttpHandler)--------把请求的资源 ...

  7. MVC-Razor引擎布局

    ViewBag.Title:标题 layout: @ViewBag.Title view: @{ViewBag.Title="标题"} @RenderBody():视图的内容直接渲 ...

  8. 破坏之王——ddos攻击与防范 读书笔记

    好久没写博客了,最近把绿盟的<破坏之王——ddos攻击与防范>又翻了一下,整理了关于DDOS分类和原理的xmind图~~ 百度云盘:http://pan.baidu.com/s/1i3ms ...

  9. C++函数转换成C#函数

            ///                        /// </param>         /// <returns></returns>    ...

  10. python 读写文本文件

    本人最近新学python ,用到文本文件的读取,经过一番研究,从网上查找资料,经过测试,总结了一下读取文本文件的方法. 1.在读取文本文件的时无非有两种方法: a.f=open('filename', ...