小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

WebAPI下的如何實現(xiàn)參數(shù)綁定

 集微筆記 2014-07-10

本文將概述在WebAPI方式下將如何將參數(shù)綁定到一個action方法,包括參數(shù)是如何被讀取,一系列規(guī)則決定特定環(huán)境采用的那種綁定方式,文章最后將給出一些實際的例子。

Parameter binding說到底是接到一個Http請求,將其轉換成.NET類型使得action方法的簽名更易于理解。

請求消息(request message)包括了請求的所有信息,如帶查詢字符串的請求地址(URL),內(nèi)容主體(content body)及頭部信息(header)。在沒有采用parameter binding

的情況下,每個action方法將需要接收request message,并手動從中提取出參數(shù),如下所示:

public object MyAction(HttpRequestMessage request)
{
        // make explicit calls to get parameters from the request object
        int id = int.Parse(request.RequestUri.ParseQueryString().Get("id")); // need error logic!
        Customer c = request.Content.ReadAsAsync<Customer>().Result; // should be async!
        // Now use id and customer
}

很顯然,這樣的方式丑陋,易出錯,代碼重復,而且難以單元測試。我們希望action的簽名類似以下的形式:

public object MyAction(int id, Customer c) { }

那么WebAPI是如何將request message轉換成像id和customer這樣的參數(shù)的呢?

Model Binding vs. Formatters

參數(shù)綁定有兩種技術:Model Binding和Formatters。實際上,WebAPI使用model binding讀取查詢字符串(query string)內(nèi)容進行參數(shù)綁定,使用Formatters讀取主體內(nèi)容

(body content)進行參數(shù)的綁定。

  • Using Model Binding:

ModelBinding和MVC中的此概念是一致的,更多內(nèi)容見Here。通常有一個"ValuePeoviders"提供數(shù)據(jù)片斷如查詢字符串參數(shù),model binder將這些片斷組合成一個對象。

  • Using Formatters:

Formatters(如MediaTypeFormatter類所示)實際上是包含額外元數(shù)據(jù)的序列化程序。WebAPI從HttpConfiguration中獲取一個formatters的列表,然后通過request信息

中的content-type來判斷采用具體合適的formatter。WebAPI有不少默認的formatters。默認的JSON formatter是JSON.NET。還有Xml formatter和采用JQuery語法的

FormUrl formatter。

其中Formatters的核心方法是MediaTypeFormatter.ReadFromStreamAsync,如下所示:

public virtual Task<object> ReadFromStreamAsync(
Type type,
Stream stream,
HttpContentHeaders contentHeaders,
IFormatterLogger formatterLogger)

其中,Type指代參數(shù)的類型,將傳遞給序列化器serializer。Stream是請求信息的content stream。Read方法將讀取stream,將其實例化為一個對象,然后返回它。

HttpContentType來自請求信息。IFormatterLogger是一個回調接口,fomatter正是通過此接口來記錄讀取中的錯誤。

model binding和formatter都支持驗證和錯誤信息記錄。然后,相比formatter而言model binding更靈活。

何時采用特定的參數(shù)綁定方式?(when do we use which?)

以下這些基本原則決定了parameter是通過modelbinding還是formatter來讀取的:

如果參數(shù)未添加任何特性字段[attribute]標明,那么這將由參數(shù)的.NET類型來決定具體采用何種方式。簡單類型"Simple types"采用model binding。復雜類型"Complex types"

  1. 采用formatters。簡單類型包括:primitives,Timespan,DateTime,Guid,Decimal,String,或者通過類型轉換器(TypeConverter)從字符串轉換過來的類型。
  2. 通過使用[FormBody]特性標示特定參數(shù)應該從body中取值。
  3. 通過使用[ModelBinder]特性來標示參數(shù)或參數(shù)類型應該使用model bound方式。這個特性也可以用來配置model binder。[FromUri]是一個從[ModelBinder]繼承而來的
    實體,用于配置model binder只應用到URL中的數(shù)據(jù)。
  4. body只能被讀取一次。如果簽名中有兩個負責類型,至少其中一個必須添加[ModelBinder]特性標注。

以下是使得這些原則得以穩(wěn)定并可預測的關鍵設計。

(body 只能被讀取一次)Only one thing can read the body

MVC和WebAPI之間的一個關鍵不同點在于MVC緩存請求主體(request body)。這意味著MVC的參數(shù)綁定可以反復從body中查找參數(shù)片斷。然而,在WebAPI中,請求主體(HttpContent)

只能被讀取一次,不被緩存,只能向前讀取的流。這意味著parameter binding需要謹慎對待stream,除非在需要綁定參數(shù)的情況下,否則stream不能被讀取。

以下的action方法想直接讀取stream,因而導致WebAPI不能保證其擁有用于參數(shù)綁定的stream??紤]如下的action方法:

        // Action saves the request’s content into an Azure blob 
        public Task PostUploadfile(string destinationBlobName)
        {
            // string should come from URL, we’ll read content body ourselves.
            Stream azureStream = OpenAzureStorage(destinationBlobName); // stream to write to azure
            return this.Request.Content.CopyToStream(azureStream); // upload body contents to azure. 
        }

參數(shù)是一個簡單類型,因而這將從查詢字符串中讀取。由于action簽名中并不包含任何 負責類型,WebAPI將永遠不會讀取request content stream,因而這里的action方法可以讀取它。

示例

以下給出一些不同請求的示例說明它們將如何映射到特定action簽名:

/?id=123&name=bob 
void Action(int id, string name) // 所有參數(shù)都是簡單類型,因而都將來自url

 

/?id=123&name=bob 
void Action([FromUri] int id, [FromUri] string name) // 同上

void Action([FromBody] string name); //[FormBody]特性顯示標明讀取整個body為一個字符串作為參數(shù)

public class Customer {   // 定義的一個復雜對象類型 
  public string Name { get; set; } 
  public int Age { get; set; } 
}

/?id=123 
void Action(int id, Customer c) // 參數(shù)id從query string中讀取,參數(shù)c是一個復雜Customer對象類戲,通過formatter從body中讀取

void Action(Customer c1, Customer c2) // 出錯!多個參數(shù)都是復雜類型,都試圖從body中讀取,而body只能被讀取一次

void Action([FromUri] Customer c1, Customer c2) // 可以!不同于上面的action,復雜類型c1將從url中讀取,c2將從body中讀取

void Action([ModelBinder(MyCustomBinder)] SomeType c) // 標示使用特定的model binder來解析參數(shù)

[ModelBinder(MyCustomBinder)] public class SomeType { } // 通過給特定類型SomeType聲明標注[ModelBidner(MyCustomBinder)]特性使得所有SomeType類型參數(shù)應用此規(guī)則 

void Action(SomeType c) // 由于c的類型為SomeType,因而應用SomeType上的特性決定其采用model binding

與MVC的區(qū)別

以下是MVC和WebAPI在參數(shù)綁定上的一些不同點:

  1. MVC只具有model binding,而沒有formatters。這是由于MVC將對request body也應用model bind 進行解析,而WebAPI對request body將使用serializer來解析。
  2. MVC將緩存request body,因而能夠很容易的將其傳遞給model binding。WebAPI不緩存request body,因而默認將不對request body應用model binding解析。
  3. WebAPI的綁定完全可以通過action簽名的類型來決定。比如:在WebAPI中,我們知道一個參數(shù)最終將從body還是query string中讀取綁定。然而,在MVC中,model binding
    系統(tǒng)將同時查找body和query string數(shù)據(jù)進行解析綁定。


 

 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多