ASP.NET Core MVC 模型綁定用法及原理
前言
查詢了一下關於 MVC 中的模型綁定,大部分都是關於如何使用的,以及模型綁定過程中的一些用法和概念,很少有關於模型綁定的內部機制實現的文章,本文就來講解一下在 ASP.NET Core MVC 中模型綁定是如何實現的,以及它的一些其他用法。
模型綁定的用途通常情況下,我們在使用 MVC 框架的時候不需要關注模型綁定的相關功能,因為它是集成到 MVC 框架內部的,當我們在瀏覽器訪問一個地址的時候,無論是 GET 還是 POST 訪問,在映射到 Action 的過程中 MVC 框架已經自動的進行了對象或者是路由參數的綁定,這其中就是使用的模型綁定。
在 ASP.NET Core MVC 中,模型綁定分為簡單模型綁定和複雜模型綁定。簡單的模型綁定比如直接從 Form 表單或者 URL 路由數據中獲取信息,然後應用到Action方法的各個參數上,複雜模型綁定的話可能就不是簡單的轉換到參數的值上面了,可能中間還會涉及到一些數據類型轉換,模型分解,參數校驗等。
下面來看一下模型綁定的一個示例:
假設我們有一個ViewModel對象叫 Person
,它的代碼如下:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
在這個 ViewModel 對象中,都是使用的一些很簡單的類型,那麼我們的 Action 進行如下的定義:
public class PersonController
{
[HttpPost]
[Route("~api/person/add")]
public IActionResult CreatePerson(Person person)
{
return Ok(person);
}
}
在上面的代碼中,我們可以向 http://localhost:5000/api/person/add
這個地址發送一個 POST 請求,Body 類型使用普通的 Form ,參數使用上面Person
定義的Name
,Age
。 在 Action 上添加斷點,我們就可以看到person變數中的值,然後此 Action 會返回一個被 json 序列化後的結果對象。
這樣一個過程,就是模型綁定在實際開發中的一個用途和用法。
是不是看起來很簡單呢?但是在內部模型綁定子系統是比較複雜的,由很多部分組成。
模型綁定的一些用法在 ASP.NET Core MVC 中,支持以下表單類型的模型綁定。
[FromHeader]
,[FromQuery]
,[FromRoute]
,[FromForm]
示例:
public IActionResult CreatePerson([FromForm]Person person)
{
return Ok(person);
}
這些 [FromXXX]
是告訴模型綁定在解析的過程中從HttpContext中那一部分獲取信息。
還有一部分模型綁定框架中定義的一些 Attribute 是用來在模型模型的過程中限制或者忽略一些參數。比如
[BindRequired]
,[BindNever]
這兩個是用來在模型綁定的過程中添加的一些制約,BindRequired
可以應用在類或者屬性上,用來限制在綁定的過程中必須需要的一些值。BindNever
用來忽略當前參數的綁定。
還有兩個 [FromServices]
,[FromBody]
。
[FromServices]
是參數綁定的過程中,告訴模型綁定框架該參數從 DI 容器中獲取。
[FromBody]
是參數綁定的過程中,告訴框架該參數是使用配置過的格式化程序從Http Body 中解析。
在[FromBody]中,默認情況下會使用MVC框架內部配置的 JsonInputFormatter 進行反序列化解析,如果你傳遞的 Body 中的類型是 application/xml,你可以在 ConfigureServices 方法中配置
services.AddMvc.AddXmlSerializerFormatters;
進行XML的反序列化。
還有一個 [ModelBinder]
這個可能很多人沒用過,這個是應用在 Controller 中的屬性上的,用來綁定屬性信息。比如
public class Controller
{
[ModelBinder]
public string Name { get; set;}
public IActionResult CreatePerson(Person person)
{
return Ok(person);
}
}
在 Action 激活的時候,Controller 的 Name 屬性也會具有Action 參數中 person 變數中名字和 Name 相同參數的值。
自定義模型綁定自定義模型綁定屬於 MVC 模型綁定的一些高級知識,在一些特殊情況中我們可能會使用到他們。 詳情可以參考這篇 文章 https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding,本文不打算做過多介紹。
MVC 模型綁定(ModelBinding)實現原理看過我 ASP.NET Core MVC Action 激活這篇文章的同學應該知道,在 Action 激活的過程中會涉及到很多狀態,那麼模型綁定是在ActionBegin
這個狀態中進行的,同時在ActionNext
過程中被使用,我就直接接著這篇文章的 Action 執行部分進行講解了。
首先,模型綁定的入口位於 ControllerActionInvoker
這個類中的一個Next方法里
private Task Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted){
......
switch (next)
{
case State.ActionBegin:
BindArgumentsAsync;
goto case State.ActionNext;
case State.ActionNext:
_actionExecutingContext = new ActionExecutingContext(_arguments);
}
......
}
可以看到在 State.ActionBegin
這個過程中使用了BindArgumentsAsync
進行參數綁定,那麼整個綁定過程就由此開始。
在 Core MVC 框架模型綁定部分源碼中,模型綁定源碼分為這幾部分:元數據(Metadata),值提供器(ValueProvider),驗證者(Validator),綁定器(Binder)。
元數據:元數據相當於模型綁定中的實體對象,用來儲存在整個模型綁定子系統中需要的各種必要信息和元數據信息,包括模型參數的元數據和以及綁定信息的元數據等等。
值提供器:值提供器用來提供在運行時模型綁定器可以從中提取值的一個Provider, 默認情況下,值提供器會從以下地方提取各種資源的值:
1、以前綁定的操作參數(當該操作為子操作時)
2、表單欄位 (FormValueProvider)
3、路由數據 (RouteValueProvider)
4、查詢字元串參數 (QueryStringValueProvider)
5、JQuery 表單數據(JQueryFormValueProvider)
這些 ValueProvider 對象由 CompositeValueProvider
進行統一管理,它是一個集合用來創建或者獲取這些 ValueProvider 對象。
驗證者:驗證者是用來驗證Action參數中模型欄位的合法性。
它的默認實現是 DefaultObjectValidator
,它會根據元數據信息來確定綁定過程中使用的具體 ValudatorProvider 對象,ValudatorProvider 是用來提供IModelValidator
介面實例對象的。
在 ASP.NET Core MVC 中有兩個類實現了 IModelValidator
介面,他們分別是DataAnnotationsModelValidator
和ValidatableObjectAdapter
。 其中ValidatableObjectAdapter
是一個適配器,用來轉換和封裝驗證結果,所以我們主要看DataAnnotationsModelValidator
。
DataAnnotationsModelValidator
就是用來驗證模型類中的各種 Attribute 的,也就是DataAnnotations
相關的那些類,比如[MaxLength]
,[Required]
,[RegularExpression]
等等。
綁定器: 綁定器用來綁定Action參數中的大多數簡單和複雜的數據模型,它通過對模型各個屬性使用遞歸邏輯來實現該目標。
針對不同類型的綁定具有不同的綁定器,如:
ArrayModelBinder
,SimpleTypeModelBinder
,FormFileModelBinder
,
FormCollectionModelBinder
,ComplexTypeModelBinder
,
BodyModelBinder
,HeaderModelBinder
,DictionaryModelBinder
,
ServicesModelBinder
,KeyValuePairModelBinder
,ByteArrayModelBinder
,
CancellationTokenModelBinder
,CollectionModelBinder
,BinderTypeModelBinder
這些 ModelBinder 對象都具有各自的 Provider 對象,對來返回當前Binder對象的實例對象。
這些 ModelBinder 對象由 ParameterBinder
進行統一管理,ParameterBinder
對象會接收模型的元數據信息(Metadata),綁定器工廠(BinderFactory),驗證者(Validator),然後進行最終的模型綁定流程,如下圖:
我們回到 ControllerActionInvoker
這個中,BindArgumentsCoreAsync
這個函數中會進行上層的模型綁定,流程如下:
以上總流程的前兩步就是 MVC Core 模型綁定系統針對於 Controller 中 Action 參數的綁定,實際上除了針對 Action 參數綁定外,還會對 Controller 中的使用了 [IModelBinder]
特性的進行綁定,那麼第三步就是在做這個事情。
至此,模型綁定流程結束。
總結在本篇中,我們學習了在 ASP.NET Core MVC 中模型綁定的一些用途和一些基本的用法,然後學習了 MVC框架中模型綁定的一些內部實現原理,通過這個學習我們可以對整個模型綁定系統更加的系統的一個了解,以便於我們有在工作系統的時候可以針對於模型綁定系統進行擴展。
如果你覺得本篇博客對你有幫助的話,感謝您的【推薦】。
如果你對 ASP.NET Core 有興趣的話可以關注我,我會定期的在博客分享我的學習心得。
本文地址:http://www.cnblogs.com/savorboard/p/aspnetcore-modelbinding.html
作者博客:Savorboard
歡迎轉載,請在明顯位置給出出處及鏈接


※TensorFlowSharp入門使用C#編寫TensorFlow人工智慧應用
※jmeter IP欺騙功能實現
※Quartz.net 定時任務之簡單任務
※演算法系列「希爾排序」篇
TAG:科技優家 |
※綁定PRESS.one
※ASP.NET Web Forms 數據綁定
※綁定余文樂同款眼鏡!MADNESS x NATIVE SONS 聯名二次開啟!
※Dota2 OMG綁定模型的技能
※CoinHot發布綁定 Telegram 賬號送 CHT 活動的公告
※SteamVR Input:如何為新控制器重新綁定VR遊戲
※SpringMVC筆記(3):數據綁定
※Whonow:一款可實時執行DNS重綁定測試的DNS伺服器
※Gosha Rubchinskiy再次放大招!這次綁定了DIESEL!
※WSDL 的綁定
※微軟智能助理Cortana上架獨立APP 不再綁定系統使用
※A BATHING APE再次綁定川久保玲!推出獨佔單品這麼豐富?
※Google Pay支持綁定Paypal賬戶 可在Gmail等應用中直接使用Paypal支付
※WF卡可以綁定PayPal嗎?WF卡用作收取PayPal付款時要提交什麼資料
※美國支付公司Shift推出比特幣借記卡 可與Coinbase賬戶直接綁定
※使用BCH支持的Member客戶端可以將信息綁定到任意位置
※Vue.js 組件中的v-on綁定自定義事件理解
※乾貨:Shopee、JD、Souq綁定連連支付收款賬戶教程
※巴斯夫推出Ultrafuse 316L綁定金屬線材
※如何在 Linux/Unix 之上綁定 ntpd 到特定的 IP 地址