一. 背景

  提到MVC不得不说MVC中的各种Result,这些高度封装的xxxResult以及在xxxResult再度封装的xxx,大大提高了MVC框架的开发效率。

  相信做过MVC开发的朋友都会用到过 return Content("xx"), 给客户端的Ajax请求返值,那么Content内部是怎么实现的呢?Content和ContentResult之间又是什么关系呢?ContentResult内部又是怎么实现的呢?

  与此类似的还有很多:Json方法和JsonResult、JavaScript方法和JavaScriptResult、Empty方法和EmptyResult 等等。

  解决上面的问题之前,我们需要准备两件利器

  ①:ILSpy代码反射工具(网上下载破解版)。

  ②:Reflector Vs的反射插件(通过Nuget下载)。

  有了上面这两种利器中任何一种,就可以清晰的看到各种Result中的代码实现了。

  下面以Content为例,简单介绍一下大致思路,在第二模块,将详细介绍每个Result。

  ①:Content方法是返回值为ContentResult类型的一个方法,即new了一个ContentResult类进行return,代码如下图:

  

  ②:ContentResult类内部又是怎么实现的呢?代码如下,最后核心代码是通过 response.write(""),向客户端返回了一个字符串。

  

  总结:经过这两步,Content也好,ContentResult也好,原理就很清晰了,下面同样按照这个套路,详细的分析各种Result的内部原理,以及测试其使用情况。

二. 逐个分析

1. ActionResult

①:它是一个抽象类,且包含一个抽象方法ExecuteResult,各种Result都直接或间接继承ActionResult,并实现ExecuteResult方法。

②:应用于Action方法前面的类型,它是Action的返回值,代表Action的执行结果。

源码如下:

代码测试:指向页面

  public ActionResult Index()
{
return View();
}

2. JsonResult

①:继承了ActionResult,实现了ExecuteResult方法。

②:解读源码可知,JsonResult内部实现原理是调用了JavaScriptSerializer对象中的Serialize方法,将Json对象转换成了Json字符串,

  通过:response.Write(javaScriptSerializer.Serialize(this.Data)); 传递给前台。

③:默认是进制Get请求访问的. JsonRequestBehavior.DenyGet。

④:在MVC的Action中,return Json(),这里的Json通过源码可知,即new了一个JsonResult对象而已,并且MVC中封装了很多重载。

⑤:应用于action充当APP接口的情况,且返回Json字符串,但ajax接受到后,会自动转换成Json对象进行使用。

源码如下:

代码测试:

       /// <summary>
/// 通过Index1页面向该方法发送请求
/// 前端拿到的是JSON字符串,需要前端转换
/// </summary>
/// <returns></returns>
public ActionResult GetInfor()
{
var data =new
{
id="",
name="mr"
};
string data2 = new JavaScriptSerializer().Serialize(data);
return Json(data2, JsonRequestBehavior.AllowGet);
}
/// <summary>
/// 前端拿到的是JSON对象,前端可以直接调用
/// </summary>
/// <returns></returns>
public ActionResult GetInfor2()
{
var data = new
{
id = "",
name = "mr"
};
return Json(data, JsonRequestBehavior.AllowGet);
}

测试结果:一个返回了Json对象,一个返回了Json字符串

3. JavaScriptResult

①:继承了ActionResult,实现了ExecuteResult方法。

②:解读源码可知:JavaScriptResult内部实现原理,设置了返回参数类型 response.ContentType = "application/x-javascript";

然后通过: response.Write(this.Script);将js代码返回前台。

可以举一反三:通过ContentResult并且设置其类型为"application/x-javascript",可以达到ContentResult同样的效果。

③:在MVC的Action中,return JavaScript(),这里的JavaScript通过源码可知,即new了一个JavaScriptResult对象而已,并且MVC中封装了很多重载。

④:应用于通过后台返给前端js代码。

源码如下:

代码测试:下面两段代码的结果是一致的

      public ActionResult GetJs()
{
return JavaScript("alert('我是js代码,调用的是JavaScriptResult')");
}
public ActionResult GetJs2()
{
return Content("alert('我是js代码,调用的是ContentResult,并自定义的返回类型为js')", "application/x-javascript");
}

4. ContentResult

①:继承了ActionResult,实现了ExecuteResult方法。

②:解读源码可知,ContentResult内部实现原理直接将数据通过这个方法Response.Write(string s)直接返回。

③:在MVC的Action中,return Content(),这里的Content通过源码可知,即new了一个ContentResult对象而已,并且MVC中封装了很多重载,可以手动设置的返回类型。

④:应用于返回一个简单的判断字段,默认表示一个文本内容,如下面的例子。

代码测试:下面两段代码效果原理是一致的。

         /// <summary>
/// 下面这两种情况达到的效果是一致的,原理也一致
/// </summary>
public void GetInfor3()
{
Response.Write("ok");
}
public ActionResult GetInfor4()
{
return Content("ok");
}

5. EmptyResult

①:继承了ActionResult,实现了ExecuteResult方法。

②:解读源码可知:EmptyResult内部实现原理,实际上它的ExecuteResult方法中为空,什么也没有。

③:在MVC的Action中,return Empty(),这里的Empty通过源码可知,即new了一个EmptyResult对象而已,并且MVC中封装了很多重载。

④:这里的EmptyResult起到一个适配器作用,一个中转的作用,可以应用于请求不需要显示页面的情况。

6. RedirectResult

①:继承了ActionResult,实现了ExecuteResult方法。

②:解读源码可知:RedirctResult内部实现原理,实际上它的ExecuteResult方法调用的是context.HttpContext.Response.Redirect(text, false)。

③:在MVC的Action中,return Redirct(),这里的Redirct通过源码可知,即new了一个RedirctResult对象而已。

④:应用于在后台进行跨站点跳转和同站点间action之间进行跳转。

源码如下:

代码测试:同站点和跨站点间的跳转。

        /// <summary>
/// 跨站点跳转
/// </summary>
/// <returns></returns>
public ActionResult RedirctToBaidu()
{
return Redirect("http://www.baidu.com");
}
/// <summary>
/// 同站点间action之间进行跳转
/// </summary>
/// <returns></returns>
public ActionResult RedictOtherAction()
{
return Redirect("/Third/GetInfor4");
}

7. RedirectToRouteResult

①:也是与页面跳转相关的。

②:mvc中 return RedirectToAction(""); return RedirectToRoute();都是跳转的一些变种,这里不再详细分析了。

8. FileResult

①:继承了ActionResult,实现了ExecuteResult方法。

②:解读源码可知:FileResult 内部实现原理,实际上它的ExecuteResult方法调用的是WriteFile(response)。

③:MVC的Action中,return File(),即new了一个FileResult对象而已.有多个重载。

④:应用于下载文件,验证码的例子。

第五节:从源码的角度理解各种Result(ActionResult、JsonResult、JavaScriptResult等)的更多相关文章

  1. [转]Android Volley完全解析(四),带你从源码的角度理解Volley

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17656437 经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了,但是 ...

  2. Android Volley完全解析(四),带你从源码的角度理解Volley

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17656437 经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了,但是 ...

  3. Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流程

    在本系列的上一篇文章中,我们学习了Glide的基本用法,体验了这个图片加载框架的强大功能,以及它非常简便的API.还没有看过上一篇文章的朋友,建议先去阅读 Android图片加载框架最全解析(一),G ...

  4. 第九节:从源码的角度分析MVC中的一些特性及其用法

    一. 前世今生 乍眼一看,该标题写的有点煽情,最近也是在不断反思,怎么能把博客写好,让人能读下去,通俗易懂,深入浅出. 接下来几个章节都是围绕框架本身提供特性展开,有MVC程序集提供的,也有其它程序集 ...

  5. Java源码解析——集合框架(五)——HashMap源码分析

    HashMap源码分析 HashMap的底层实现是面试中问到最多的,其原理也更加复杂,涉及的知识也越多,在项目中的使用也最多.因此清晰分析出其底层源码对于深刻理解其实现有重要的意义,jdk1.8之后其 ...

  6. Android AsyncTask完全解析,带你从源码的角度彻底理解

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11711405 我们都知道,Android UI是线程不安全的,如果想要在子线程里进 ...

  7. [转]Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

    Android事件分发机制 该篇文章出处:http://blog.csdn.net/guolin_blog/article/details/9097463 其实我一直准备写一篇关于Android事件分 ...

  8. 从源码的角度分析ViewGruop的事件分发

    从源码的角度分析ViewGruop的事件分发. 首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别? 顾名思义,ViewGroup就是一组View的集合,它包含很多的子View ...

  9. 从源码的角度解析View的事件分发

    有好多朋友问过我各种问题,比如:onTouch和onTouchEvent有什么区别,又该如何使用?为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?为什么图片轮播器里的图 ...

随机推荐

  1. chome(谷歌浏览器)上传文件崩溃/上传图片崩溃/打开浏览文件未响应 解决方案

    测试解决方案:关闭搜狗输入法(我用的是搜狗输入法,若使用其他输入法,此方案也可能适用),再测试是否重现浏览器崩溃问题 可选解决方案:升级搜狗输入法(如果想 卸载输入法 也可以) 前面有段时间chome ...

  2. PHAR系列之导言

    由于之前都是在现成的PHP框架下写web项目,一般都只专注于框架内部的使用跟优化.但是对于一些PHP很有特色的功能跟特性很少过多的深入了解.最近做项目调研的时候偶尔注意到一个PHP中一个比较常见的概念 ...

  3. Navicat Premium 12.0.24安装与激活(亲测已成功激活)

    另请参见:Navicat Premium 12.0.18 / 12.0.24安装与激活 另请参见:Navicat Premium 12安装与激活(亲测已成功激活) 说明: 本主亲自验证过,可以激活! ...

  4. python 之 查找某目录中最新的文件

    记录一下这个方法,感觉很有用!>.< import os def find_newest_file(path_file): lists = os.listdir(path_file) li ...

  5. DP思想笔记

    一.思想 DP也是把复杂的问题分解为许多子问题,与分治法不同的是,分治法的各个子问题互相之间没有联系,而动态规划却有.前一个子问题的结果与下一步的子问题的结果是什么有关系.这就决定了DP算法肯定有一个 ...

  6. 产品设计-后台管理权限设计RBAC

    最近在做OA系统,设计到不同的员工会拥有不同权限对OA进行操作,总结了一下整体的设计 做权限的分配就是为了更好的管理不同类别的员工,如人事部可以看到普通员工的薪酬,可以查看全部员工的考勤数据请假等,而 ...

  7. 自定义JDBC链接池

    上篇简单介绍了jdbc链接数据库: 本篇就说一下自定义连接池以及增删改查的测试: 自定义连接池 自定义链接池的原因 JDBC连接中用到Connection   在每次对数据进行增删查改 都要 开启  ...

  8. JavaScript对象类型之简单介绍

    引言 对象是JavaScript的基本数据类型. 对象是一种复合值:将很多值(原始值或者其他对象)聚合在一起,通过名字访问这些值. 对象可以看做属性的无序集合,每个属性都是一个名/值对.属性名是字符串 ...

  9. SAP PS 模块,项目、WBS与网络作业概念

    项目定义 项目定义是项目的唯一标识.通过项目定义,决定了包含于其中的所有WBS元素的组织结构.计划方法.预算方式以及结算方法等信息.而项目定义中的数据,则主要来源于“项目参数文件”,所以创建项目定义时 ...

  10. django-debug-toolbar使用指南

    好久没发新博客,凑个数... django-debug-toolbar 介绍 django-debug-toolbar 是一组可配置的面板,可显示有关当前请求/响应的各种调试信息,并在单击时显示有关面 ...