第五節:從源碼的角度理解各種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對象而已.有多個重載。

④:應用於下載文件,驗證碼的例子。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM