Asp.net MVC的Model Binder工作流程以及擴展方法(2) - Binder Attribute


上篇文章中分析了Custom Binder的弊端: 由於Custom Binder是和具體的類型相關,比如指定類型A由我們的Custom Binder解析,那么導致系統運行中的所有Action的訪問參數,只要是類型A, 都會使用Custom Binder. 這篇文章將會介紹Binder Attribute方式擴展MVC的Model Binder, 這種方式更加的靈活和可操控。

本篇文章參考了ModelBinder——ASP.NET MVC Model綁定的核心, 結合Artech的這篇文章,對於MVC的Model Binder一定能夠理解的更加深刻。

閱讀目錄:

一. Asp.net MVC Model Binder的源碼分析

二. Model Binder的優先順序以及擴展點

三. 自定義Binder Attribute - SessionUserBinderAttribute

四. 應用SessionUserBinderAttribute

五. 總結

一,Asp.net MVC Model Binder的源碼分析

在實際使用Binder Attribute之前,我們先來看看Model Binder在MVC中是如何工作的。

1.1  首先, 在MVC中, 當一個請求發送到服務器,先是要經過Route匹配, 找到對應的Controller和Action, 然后才是構建Action中的參數,也就是Model Binder的過程。這個可以從MVC的源碼, ControllerActionInvoker中看出來。
在ControllerActionInvoker.cs的函數GetParameterValue函數中,調用了GetModelBinder方法來獲取構建該Action參數的Binder.

1.2 GetModelBinder方法,將會優先使用ParameterDescriptor描述中指定的Binder。這是本篇文章介紹的Model Binder擴展點 -- 為Action參數指定Binder.

1.3 在ParameterDescriptor沒有指定Binder的情況下,按照這個優先順序獲取Binder

  a. 從BinderProvoder中獲取
      b. 從global table中獲取.  第一篇中的Custom Model Binder就是這里的擴展,定義一個Model Binder注冊到global table中
      c. 從參數類型Attribute上指定的Binder獲取。參數類型定義類的定義處,也可以使用Binder Attribute,指定該類的Action參數由指定的Binder處理。
      d. 使用MVC默認的Default Binder

blog-justrun1983

 

二,Model Binder的優先順序以及擴展點

從上面MVC中Model Binder的源代碼分析中,可以知道,參數如何構建取決於Binder,而獲取Binder的源的優先順序是:

1. PrameterDescriptor
2. Binder Provider
3. Global table
4. 參數類型定義的Binder Attribute
5. MVC的DefaultBinder

所以Model Binder的擴展點也是上面5處, 第一篇文章中介紹的是擴展點3, 這篇中介紹的是擴展點1, 下篇文章中,將會介紹擴展點5,也就是DefaultBinder.

三,自定義Binder Attribute - SessionUserBinderAttribute

還是以解決上篇文章中的Session依賴問題為入手。我們定義SessionUserBinderAttribute 繼承自CustomModelBinderAttribute,重寫方法GetBinder(),該Binder將從Session中獲取值來構建Action參數。

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] 
public class SessionUserBinderAttribute : CustomModelBinderAttribute 
{ 
       public override IModelBinder GetBinder() 
       { 
           return new UserAccountModelBinder(); 
       } 
}

public class UserAccountModelBinder : IModelBinder 
{ 
       public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
       { 
           if (controllerContext.HttpContext.Session["UserAccuont"] != null) 
           { 
               return controllerContext.HttpContext.Session["UserAccuont"]; 
           } 
           return null; 
       } 
}

四,應用SessionUserBinderAttribute

使用我們的SessionUserBinderAttribute改造Index方法

原有的Index方法是這樣的:

public ActionResult Index() 
{ 
          var user = Session["UserAccuont"] as UserAccount; //從Session中獲取當前登錄用戶的信息 
          //send email 
          var email = user.Email; 
          return new EmptyResult(); 
}

改造后的函數如下, 使用SessionUserBinder指定user參數的值,是從session中獲取。

public ActionResult Index([SessionUserBinder]UserAccount user) 
{ 
           //send email 
           var email = user.Email; 
           return new EmptyResult(); 
}

同時, 如果在新增一個UserAccount表單提交的時候,由於沒有使用SessionUserBinderAttribute, 該useraccount將會由MVC中的DefaultBinder處理,也就是從form中提取值。

[HttpPost] 
public ActionResult Create(UserAccount useraccount) 
{ 
    return View(); 
}

五,總結

這篇文章中,介紹了MVC中的model binder流程,以及羅列了model binder中5個的擴展點:

1. PrameterDescriptor
2. Binder Provider
3. Global table
4. 參數類型定義的Binder Attribute
5. MVC的DefaultBinder

其中這篇文章涉及的是擴展點1.
擴展點2 Artech的文章ModelBinder——ASP.NET MVC Model綁定的核心中有介紹。
擴展點3在文章Asp.net MVC的Model Binder工作流程以及擴展方法(1) - Custom Model Binder中 
擴展點4也是利用Binder Attribute,不同的地方是,它關聯的不是參數,而是類型定義。作用和擴展點3范圍一樣,不在寫文章展開。
擴展點5是MVC中的DefaultBinder, 下篇文章中,將會詳細介紹。

Custom Model Binder是以類型指定binder, 我們比喻為全火力覆蓋,這里介紹的CustomModelBinderAttribute可以達到定點清除的效果,也就是只有我指定的參數才由特定的binder處理。理解兩者應用范圍的不同,有助於我們選擇使用哪種方式擴展。


免責聲明!

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



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