1. 程式人生 > >瞭解ASP.NET MVC幾種ActionResult的本質:HttpStatusCodeResult & RedirectResult/RedirectToRouteResult

瞭解ASP.NET MVC幾種ActionResult的本質:HttpStatusCodeResult & RedirectResult/RedirectToRouteResult

在本系列的最後一篇,我們來討論最後三個ActionResult:HttpStatusCodeResult、RedirectResult和RedirectToRouteResult 。第一個用於實現針對某個HTTP狀態的響應,而後兩個用於實現重定向。至於重定向,又分為“暫時重定向”和“永久重定向”,按照響應狀態,又稱“302重定向”和“301重定向”。[本文已經同步到《How ASP.NET MVC Works?》中]

目錄
一、HttpStatusCodeResult
二、RedirectResult
三、RedirectToRouteResult
四、“302重定向”V.S.“301重定向”

一、HttpStatusCodeResult

每一個HTTP響應均具有一個表示響應狀態的程式碼和一個可選的狀態描述,正常情況下返回“200 OK”。System.Web.Mvc.HttpStatusCodeResult使我們很容易地返回一個指定狀態的HTTP響應。如下面的程式碼片斷所示,HttpStatusCodeResult具有StatusCode和StatusDescription兩個只讀的屬性分別表示響應狀態碼和狀態描述資訊。在建構函式中既可以將狀態碼設定成一個整數,也可以以HttpStatusCode列舉形式來指定狀態碼。

   1: public class HttpStatusCodeResult : ActionResult
   2: {    
   3:     public HttpStatusCodeResult(int statusCode);
   4:     public HttpStatusCodeResult(HttpStatusCode statusCode);
   5:     public HttpStatusCodeResult(int statusCode, string statusDescription);
   6:     public HttpStatusCodeResult(HttpStatusCode statusCode, string
statusDescription);
   7:  
   8:     public override void ExecuteResult(ControllerContext context);
   9:     
  10:     public int         StatusCode { get; }
  11:     public string      StatusDescription { get;}
  12: }

HttpStatusCodeResult實現在ExecuteResult方法中的請求響應邏輯很簡單,如下面的程式碼片斷所示,它僅僅是設定了當前HttpResponse的StatusCode和StatusDescription而已。有一點值得一提的是,如果我們採用Visual Studio的Development Server作為Web應用的宿主,通過HttpStatusCodeResult的StatusDescription屬性設定的狀態描述資訊不會反映HTTP響應中,只有採用IIS作為宿主才會真正將此資訊寫入響應訊息。

   1: public class HttpStatusCodeResult : ActionResult
   2: {
   3:     //其他成員
   4:     public override void ExecuteResult(ControllerContext context)
   5:     {      
   6:         context.HttpContext.Response.StatusCode = this.StatusCode;
   7:         if (this.StatusDescription != null)
   8:         {
   9:             context.HttpContext.Response.StatusDescription = this.StatusDescription;
  10:         }
  11:     }
  12: }

HttpStatusCodeResult具有兩個子類,一個基於響應狀態“404, Not Found”的System.Web.Mvc.HttpNotFoundResult,另一個是基於響應狀態“401, Not Authorized”的System.Web.Mvc.HttpUnauthorizedResult,第7章“Action的執行”中篩選器AuthorizeAttribute在授權檢驗失敗的情況下返回的就是一個HttpUnauthorizedResult物件。

二、RedirectResult

RedirectResult幫助我們實現針對某個地址的重定向,其作用與呼叫HttpResonse的Redirect/RedirectPermanent方法完全一致。如下面的程式碼片斷所示,RedirectResult具有兩個只讀屬性Permanent和Url,前者表示採用永久重定向還是暫時重定向,預設值為False,後者表示重定向的目標地址,既可以採用絕對地址(比如http://www.asp.net),也可以採用相對地址(比如~/account/register)。

   1: public class RedirectResult : ActionResult
   2: {    
   3:     public RedirectResult(string url);
   4:     public RedirectResult(string url, bool permanent);
   5:     public override void ExecuteResult(ControllerContext context);
   6:   
   7:     public bool       Permanent { get; }
   8:     public string     Url { get; }
   9: }

暫時重定向和永久重定向可以分別通過呼叫HttpResponse的Redirect和RedirectPermanent來實現,實際上RedirectResult基於重定向的實現就是通過呼叫這兩個方法來完成的,這可以通過如下所示的ExecuteResult方法的定義看出來。

   1: public class RedirectResult : ActionResult
   2: {
   3:     //其他成員
   4:     public override void ExecuteResult(ControllerContext context)
   5:     {
   6:         //其他操作
   7:         string url = UrlHelper.GenerateContentUrl(this.Url, context.HttpContext);
   8:         if (this.Permanent)
   9:         {
  10:             bool endResponse = false;
  11:             context.HttpContext.Response.RedirectPermanent(url, false);
  12:         }
  13:         else
  14:         {
  15:             bool flag2 = false;
  16:             context.HttpContext.Response.Redirect(url, false);
  17:         }
  18:     }
  19: }

三、RedirectToRouteResult

RedirectResult使我們可以直接重定向到指定的目標地址,另一個類似的RedirectToRouteResult幫助我們根據註冊的路由進行重定向。如下面的程式碼片斷所示,RedirectToRouteResult沒有了表示重定向目標地址的Url屬性,取而代之的是表示路由註冊名稱和路由引數的RouteName和RouteValues屬性,在進行重定向時就是根據這兩個屬性根據註冊的路由解析出具體的重定向地址的。

   1: public class RedirectToRouteResult : ActionResult
   2: {   
   3:     public RedirectToRouteResult(RouteValueDictionary routeValues);
   4:     public RedirectToRouteResult(string routeName, RouteValueDictionary routeValues);
   5:     public RedirectToRouteResult(string routeName, RouteValueDictionary routeValues, bool permanent);
   6:     public override void ExecuteResult(ControllerContext context);
   7:    
   8:     public bool                     Permanent { get; }
   9:     public string                   RouteName { get; }
  10:     public RouteValueDictionary     RouteValues { get; }
  11: }

抽象類Controller中定義了一系列建立RedirectResult/RedirectToRouteResult的方法,比如Redirect/RedirectPermanent方法用於建立重定向到指定URL的RedirectResult,RedirectToAction/RedirectToActionPermanent用於建立重定向到指定的目標Action的RedirectResult/RedirectToRouteResult,而RedirectToRoute/RedirectToRoutePermanen建立的RedirectResult/RedirectToRouteResult物件是針對註冊的某個路由的。

四、“302重定向”V.S.“301重定向”

暫時重定向和永久重定向有時又被稱為“302重定向”和“301重定向”,302和301表示響應的狀態碼。當我們呼叫HttpResponse的Redirect/RedirectPermanent方法時,除了會設定相應的響應狀態碼之外,還會將重定向的目標地址寫入響應報頭(Location),瀏覽器在接收到響應之後自動發起針對重定向目標地址的訪問。

   1: public class HomeController : Controller
   2: {
   3:     public ActionResult Redirect()
   4:     {
   5:         return Redirect("http://www.asp.net");
   6:     }
   7:  
   8:     public ActionResult RedirectPermanent()
   9:     {
  10:         return RedirectPermanent("http://www.asp.net");
  11:     }
  12: }

在上面的程式碼片斷中,我們定義了採用暫時重定向和永久重定向的Action方法Redirect和RedirectPermanent,如果我們通過瀏覽器分別對它們發起訪訪問,會得到具有如下內容的兩個響應。兩種重定向的不同作用主要體現在SEO(Search engine optimization)上,搜尋引擎會使用永久重定向目標地址更新自己的索引,對於暫時重定向則不會。

   1: //1、Redirect
   2: HTTP/1.1 302 Found
   3: Server: ASP.NET Development Server/10.0.0.0
   4: Date: Wed, 13 Jun 2012 09:34:15 GMT
   5: X-AspNet-Version: 4.0.30319
   6: X-AspNetMvc-Version: 4.0
   7: Location: http://www.asp.net
   8: Cache-Control: private
   9: Content-Type: text/html; charset=utf-8
  10: Content-Length: 135
  11: Connection: Close
  12:  
  13: <html><head><title>Object moved</title></head><body><h2>Object moved to <a href="http://www.asp.net">here</a>.</h2></body></html>
  14:  
  15: //2、RedirectPermanent
  16: HTTP/1.1 301 Moved Permanently
  17: Server: ASP.NET Development Server/10.0.0.0
  18: Date: Wed, 13 Jun 2012 09:34:40 GMT
  19: X-AspNet-Version: 4.0.30319
  20: X-AspNetMvc-Version: 4.0
  21: Location: http://www.asp.net
  22: Cache-Control: private
  23: Content-Type: text/html; charset=utf-8
  24: Content-Length: 135
  25: Connection: Close
  26:  
  27: <html><head><title>Object moved</title></head><body><h2>Object moved to <a href="http://www.asp.net">here</a>.</h2></body></html>