ASP.NET Web API Model-ActionBinding

來源:互聯網
上載者:User

標籤:asp.net web api   asp.net web api actionbinding   httpactionbinding   

ASP.NET Web API Model-ActionBinding前言

前面的幾個篇幅把Model部分的知識點劃分成一個個的模組來講解,而在控制器執行過程中分為好多個過程,對於控制器執行過程(一)主要講解了過濾器以及在後面的過濾器篇幅中也有講到,而在過濾器之中還有一些執行過程,也就是在授權過濾器執行完畢後,行為過濾器執行之前,我們要做的就是Model綁定,面前也都說了之前對Model的知識點模組都講解的差不多了,今天這個篇幅我們就來看一下這些零散知識點的源頭,也就是Model綁定的進入點。

 

 

Model-ActionBinding

HttpActionBinding的由來

我們通過前面幾篇的瞭解都知道在ASP.NET Web API架構中進入整個Model綁定的進入點就是在HttpActionBinding類型中,對於這個類型前面的篇幅也介紹過,它裡面封裝了ParameterBinding數組,這些ParameterBinding就是控制器方法中每個參數執行Model綁定的對象了,既然我們知道HttpActionBinding類型中有著許多ParameterBinding類型的對象執行個體,那麼我們就要看看HttpActionBinding類型是怎麼產生的。

範例程式碼1-1

this.SetSingle<IActionValueBinder>(new DefaultActionValueBinder());

首先我們看到範例程式碼1-1中可以看到在HttpConfiguration類型的服務容器中,預設註冊為IActionValueBinder類型服務的是DefaultActionValueBinder類型。

範例程式碼1-2

namespace System.Web.Http.ModelBinding{    public class DefaultActionValueBinder : IActionValueBinder    {        public DefaultActionValueBinder();        public virtual HttpActionBinding GetBinding(HttpActionDescriptor actionDescriptor);        protected virtual HttpParameterBinding GetParameterBinding(HttpParameterDescriptor parameter);    }}


代碼1-2中所示的是DefaultActionValueBinder類型的定義,其中的這兩個方法很重要,第一個GetBinding()方法是用以架構內部來進行調用,根據HttpActionDescriptor控制器方法描述類型對象擷取到我們所需的HttpActionBinding,而其內部實現則是調用下面的GetParameterBinding()方法,利用HttpActionDescriptor對象擷取到HttpParameterDescriptor集合後,然後遍曆的去調用GetParameterBinding()方法,從而能夠擷取到HttpParameterBinding對象執行個體,最後產生HttpActionBinding對象執行個體,從設計角度來看這個DefaultActionValueBinder類型中的兩個方法GetBinding()和GetParameterBinding()方法都是採用了templatemethod模式,這種模式在架構設計中很常見。

 

HttpParameterBinding的由來

下面我們就要來說說GetParameterBinding()方法的細節實現了因為關乎著使用哪種方式來進行綁定。也就是根據HttpParameterDescriptor類型執行個體怎麼去建立HttpParameterBinding的。

範例程式碼1-3

    protected virtual HttpParameterBinding GetParameterBinding(HttpParameterDescriptor parameter)    {        ParameterBindingAttribute parameterBinderAttribute = parameter.ParameterBinderAttribute;        if (parameterBinderAttribute == null)        {            ParameterBindingRulesCollection parameterBindingRules = parameter.Configuration.ParameterBindingRules;            if (parameterBindingRules != null)            {                HttpParameterBinding binding = parameterBindingRules.LookupBinding(parameter);                if (binding != null)                {                    return binding;                }            }            Type parameterType = parameter.ParameterType;            if (TypeHelper.IsSimpleUnderlyingType(parameterType) || TypeHelper.HasStringConverter(parameterType))            {                return parameter.BindWithAttribute(new FromUriAttribute());            }            parameterBinderAttribute = new FromBodyAttribute();        }        return parameterBinderAttribute.GetBinding(parameter);     }

代碼1-3就是具體的實現了,那我們就就來看一下其中的過程以及會涉及到的類型。

首先會根據參數HttpParameterDescriptor類型執行個體擷取到在這個控制器方法參數上使用了ParameterBindingAttribute標識,並且擷取ParameterBindingAttribute類型執行個體。我們暫且就來看一下ParameterBindingAttribute類型定義。

範例程式碼1-4

    [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]    public abstract class ParameterBindingAttribute : Attribute    {        // Methods        protected ParameterBindingAttribute();        public abstract HttpParameterBinding GetBinding(HttpParameterDescriptor parameter);    }


從代碼1-4可以看出,這個ParameterBindingAttribute類型適用於類型以及參數,也就是說我們選擇綁定的方式可以在Model類型定義的時候標識這個特性,也可以在定義控制器方法的時候適當的給參數這個特性標識。

然而在這個類型中為什麼會有GetBinding()方法呢?因為這個類型是抽象類別型,也就是採用了上面所說過的template method模式,而在子類實現中,根據自身適應的情況產生響應的HttpParameterBinding類型。看下如下的圖表示相關的物件模型。

圖1

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/4A/43/wKiom1QkAmWB6y-1AAFXRa7CSws421.jpg" title="ModelBinder1.png" width="738" height="237" border="0" hspace="0" vspace="0" style="width:738px;height:237px;" alt="wKiom1QkAmWB6y-1AAFXRa7CSws421.jpg" />

上面圖1中涉及到的每個類型大家可以去看前面的篇幅,篇幅中有遺漏的就麻煩大家自己多動一下手去看看吧。

 

HttpParameterBinding的選擇機制

 

接著代碼1-3的思緒,在我們擷取到了ParameterBindingAttribute之後,並不知道這個控制器方法中的參數是否標識有ParameterBindingAttribute,或者是參數類型上是否有標識。這個時候假使是有的話,可以看到代碼1-3中的最後一句代碼,直接使用擷取到的ParameterBindingAttribute類型進行調用GetBinding()方法,也就是在上一小節中圖1所示的那樣。

然而還有一種情況,就是我們在定義控制器方法的時候參數沒有明確的標識我們要使用某種綁定機制,或者是在定義Model的時候沒有明確的表示,這個時候架構則會從定義好的規則集合中根據當前控制其方法參數的描述類型來擷取對應的ParameterBinding類型執行個體。如下的範例程式碼定義了規則集合的定義。

範例程式碼1-5

    internal static ParameterBindingRulesCollection GetDefaultParameterBinders()    {        ParameterBindingRulesCollection ruless = new ParameterBindingRulesCollection();        ruless.Add(typeof(CancellationToken), parameter => new CancellationTokenParameterBinding(parameter));        ruless.Add(typeof(HttpRequestMessage), parameter => new HttpRequestParameterBinding(parameter));        ruless.Add(delegate (HttpParameterDescriptor parameter) {            if (!typeof(HttpContent).IsAssignableFrom(parameter.ParameterType))            {                return null;            }            return parameter.BindAsError(Error.Format(SRResources.ParameterBindingIllegalType, new object[] { parameter.ParameterType.Name, parameter.ParameterName }));        });        return ruless;     }


代碼1-5中所表示的就是規則定義,意思就是在我們使用HttpParameterDescriptor類型執行個體來從集合中想擷取ParameterBinding的時候,ParameterBindingRulesCollection類型會把我們的HttpParameterDescriptor類型執行個體中的ParameterType取出來和之前定義的每一項規則的類型進行比對,類型吻合了就會隨之調用對應的委託類型進行ParameterBinding產生。從代碼1-5中我們可以看到的是規則中只有CancellationToken類型和HttpRequestMessage類型,假使這個時候我們的控制其方法參數類型是自訂的複雜類型,這裡也都沒有定義,這個時候架構會取出HttpParameterDescriptor類型中的ParameterType進行判斷,假使是可以轉換成string類型的簡單類型參數,則會產生一個FromUriAttribute類型作為標識,FromUriAttribute類型繼承自ModelBinderAttribute類型。

假使這裡的判斷沒有通過則說明是複雜類型,最後我們再看待代碼1-3中的定義最後產生的是FromBodyAttribute標識類型,這個時候請參照圖1。


本文出自 “金源” 部落格,請務必保留此出處http://jinyuan.blog.51cto.com/8854733/1558338

ASP.NET Web API Model-ActionBinding

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.