zoukankan      html  css  js  c++  java
  • 第五节:从源码的角度理解各种Result(ActionResult、JsonResult、JavaScriptResult等)

    一. 背景

      提到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的执行结果。

     源码如下:

    代码测试:指向页面

    1  public ActionResult Index()
    2  {
    3    return View();
    4  }

    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对象进行使用。

    源码如下:

    代码测试:

     1       /// <summary>
     2         /// 通过Index1页面向该方法发送请求
     3         /// 前端拿到的是JSON字符串,需要前端转换
     4         /// </summary>
     5         /// <returns></returns>
     6         public ActionResult GetInfor()
     7         {
     8             var data =new 
     9             {
    10                 id="1",
    11                 name="mr"
    12             };
    13             string data2 = new JavaScriptSerializer().Serialize(data);
    14             return Json(data2, JsonRequestBehavior.AllowGet);
    15         }
    16         /// <summary>
    17         /// 前端拿到的是JSON对象,前端可以直接调用
    18         /// </summary>
    19         /// <returns></returns>
    20         public ActionResult GetInfor2()
    21         {
    22             var data = new
    23             {
    24                 id = "1",
    25                 name = "mr"
    26             };
    27             return Json(data, JsonRequestBehavior.AllowGet);
    28         }

    测试结果:一个返回了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代码。

    源码如下:

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

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

    4. ContentResult

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

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

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

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

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

     1         /// <summary>
     2         /// 下面这两种情况达到的效果是一致的,原理也一致
     3         /// </summary>
     4         public void GetInfor3()
     5         {
     6             Response.Write("ok");
     7         }
     8         public ActionResult GetInfor4()
     9         {
    10             return Content("ok");
    11         }

    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之间进行跳转。

    源码如下:

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

     1        /// <summary>
     2         /// 跨站点跳转
     3         /// </summary>
     4         /// <returns></returns>
     5         public ActionResult RedirctToBaidu()
     6         {
     7             return Redirect("http://www.baidu.com");
     8         }
     9         /// <summary>
    10         /// 同站点间action之间进行跳转
    11         /// </summary>
    12         /// <returns></returns>
    13         public ActionResult RedictOtherAction()
    14         {
    15             return Redirect("/Third/GetInfor4");
    16         }

    7. RedirectToRouteResult

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

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

    8. FileResult

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

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

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

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

  • 相关阅读:
    动态规划最大利润的问题
    【转】mysql基础汇总
    mac使用frida
    Mac 下python3 [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed 解决方法
    mac使用jadx逆向app
    python桶排序代码
    requests_html使用asyncio
    async for的使用
    [转载]微信企业号:企业客户的移动应用入口
    微信服务号、订阅号、企业号差别
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/7910767.html
Copyright © 2011-2022 走看看