天天看點

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

前言:還記得剛使用WebApi那會兒,被它的傳參機制折騰了好久,查閱了半天資料。如今,使用WebApi也有段時間了,今天就記錄下API接口傳參的一些方式方法,算是一個筆記,也希望能幫初學者少走彎路。本篇針對初初使用WebApi的同學們,比較基礎,有興趣的且看看。

WebApi系列文章

<a href="http://www.cnblogs.com/landeanfen/p/5210356.html">C#進階系列——WebApi接口測試工具:WebApiTestClient</a>

<a href="http://www.cnblogs.com/landeanfen/p/5177176.html">C#進階系列——WebApi 跨域問題解決方案:CORS</a>

<a href="http://www.cnblogs.com/landeanfen/p/5287064.html">C#進階系列——WebApi身份認證解決方案:Basic基礎認證</a>

<a href="http://www.cnblogs.com/landeanfen/p/5337072.html">C#進階系列——WebApi接口傳參不再困惑:傳參詳解</a>

<a href="http://www.cnblogs.com/landeanfen/p/5501487.html">C#進階系列——WebApi接口傳回值不困惑:傳回值類型詳解</a>

<a href="http://www.cnblogs.com/landeanfen/p/5363846.html" target="_blank">C#進階系列——WebApi異常處了解決方案</a>

C#進階系列——WebApi區域Area使用小結

本篇打算通過get、post、put、delete四種請求方式分别談談基礎類型(包括int/string/datetime等)、實體、數組等類型的參數如何傳遞。

對于取資料,我們使用最多的應該就是get請求了吧。下面通過幾個示例看看我們的get請求參數傳遞。

參數截圖效果

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

 這是get請求最基礎的參數傳遞方式,沒什麼特别好說的。

如果我們在get請求時想将實體對象做參數直接傳遞到背景,是否可行呢?我們來看看。

測試結果

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

由上圖可知,在get請求時,我們直接将json對象當做實體傳遞背景,背景是接收不到的。這是為什麼呢?我們來看看對應的http請求

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

原來,get請求的時候,預設是将參數全部放到了url裡面直接以string的形式傳遞的,背景自然接不到了。

原因分析:還記得有面試題問過get和post請求的差別嗎?其中有一個差別就是get請求的資料會附在URL之後(就是把資料放置在HTTP協定頭中),而post請求則是放在http協定包的包體中。

根據園友們的提議,Get請求的時候可以在參數裡面加上[FromUri]即可直接得到對象。還是貼上代碼:

得到結果:

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

如果你不想使用[FromUri]這些在參數裡面加特性的這種“怪異”寫法,也可以采用先序列化,再在背景反序列的方式。

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

這樣在背景得到我們序列化過的對象,再通過反序列化就能得到對象。

在url裡面我們可以看到它自動給對象加了一個編碼:

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

一般get請求不建議将數組作為參數,因為我們知道get請求傳遞參數的大小是有限制的,最大1024位元組,數組裡面内容較多時,将其作為參數傳遞可能會發生參數超限丢失的情況。

為什麼會說get請求“怪異”呢?我們先來看看下面的兩種寫法對比。

這是标準寫法,背景加[HttpGet],參數正常得到:

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

為了對比,我将[HttpGet]去掉,然後再調用

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

貌似沒有任何問題!有人就想,那是否所有的get請求都可以省略掉[HttpGet]這個标注呢。我們試試便知。

我們把之前的方法名由GetByModel改成FindByModel,這個再正常不過了,很多人查詢就不想用Get開頭,還有直接用Query開頭的。這個有什麼關系嗎?有沒有關系,我們以事實說話。

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

貌似又可行,沒有任何問題啊。根據上面的推論,我們去掉[HttpGet]也是可行的,好,我們注釋掉[HttpGet],運作起來試試。

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

結果是不進斷點,有些人不信,我們在浏覽器裡面看看http請求:

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

呵呵,這就奇怪了,就改了個方法名,至于這樣麼?還真至于!

部落客的了解是:方法名以Get開頭,WebApi會自動預設這個請求就是get請求,而如果你以其他名稱開頭而又不标注方法的請求方式,那麼這個時候伺服器雖然找到了這個方法,但是由于請求方式不确定,是以直接傳回給你405——方法不被允許的錯誤。

最後結論:所有的WebApi方法最好是加上請求的方式([HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]),不要偷懶,這樣既能防止類似的錯誤,也有利于方法的維護,别人一看就知道這個方法是什麼請求。

這也就是為什麼很多人在園子裡面問道為什麼方法名不加[HttpGet]就調用不到的原因!

在WebApi的RESETful風格裡面,API服務的增删改查,分别對應着http的post/delete/put/get請求。我們下面就來說說post請求參數的傳遞方式。

 post請求的基礎類型的參數和get請求有點不一樣,我們知道get請求的參數是通過url來傳遞的,而post請求則是通過http的請求體中傳過來的,WebApi的post請求也需要從http的請求體裡面去取參數。

這是一種看上去非常正确的寫法,可是實際情況是:

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

這是一種另許多人頭痛的寫法,但是沒辦法,這樣确實能得到我們的結果:

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

我們一般的通過url取參數的機制是鍵值對,即某一個key等于某一個value,而這裡的FromBody和我們一般通過url取參數的機制則不同,它的機制是=value,沒有key的概念,并且如果你寫了key(比如你的ajax參數寫的{NAME:"Jim"}),背景反而得到的NAME等于null。不信你可以試試。

上面講的都是傳遞一個基礎類型參數的情況,那麼如果我們需要傳遞多個基礎類型呢?按照上面的推論,是否可以([FromBody]string NAME, [FromBody]string DES)這樣寫呢。試試便知。

得到結果

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結
C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

這說明我們沒辦法通過多個[FromBody]裡面取值,此法失敗。

既然上面的辦法行不通,那我們如何傳遞多個基礎類型的資料呢?很多的解決辦法是建立一個類去包含傳遞的參數,部落客覺得這樣不夠靈活,因為如果我們前背景每次傳遞多個參數的post請求都去建立一個類的話,我們系統到時候會有多少個這種參數類?維護起來那是相當的麻煩的一件事!是以部落客覺得使用dynamic是一個很不錯的選擇。我們來試試。

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

通過dynamic動态類型能順利得到多個參數,省掉了[FromBody]這個累贅,并且ajax參數的傳遞不用使用"無厘頭"的{"":"value"}這種寫法,有沒有一種小清新的感覺~~有一點需要注意的是這裡在ajax的請求裡面需要加上參數類型為Json,即 contentType: 'application/json', 這個屬性。

通過上文post請求基礎類型參數的傳遞,我們了解到了dynamic的友善之處,為了避免[FromBody]這個累贅和{"":"value"}這種"無厘頭"的寫法。部落客推薦所有基礎類型使用dynamic來傳遞,友善解決了基礎類型一個或多個參數的傳遞,示例如上文。如果園友們有更好的辦法,歡迎讨論。

上面我們通過dynamic類型解決了post請求基礎類型資料的傳遞問題,那麼當我們需要傳遞一個實體作為參數該怎麼解決呢?我們來看下面的代碼便知:

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

原了解釋:使用實體作為參數的時候,前端直接傳遞普通json,背景直接使用對應的類型去接收即可,不用FromBody。但是這裡需要注意的一點就是,這裡不能指定contentType為appplication/json,否則,參數無法傳遞到背景。我們來看看它預設的contentType是什麼:

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

為了弄清楚原因,部落客查了下http的Content-Type的類型。看到如下說明:

application/x-www-form-urlencoded : &lt;form encType=””&gt;中預設的encType,form表單資料被編碼為key/value格式發送到伺服器(表單預設的送出資料的格式);

application/json    : JSON資料格式

也就是說post請求預設是将表單裡面的資料的key/value形式發送到服務,而我們的伺服器隻需要有對應的key/value屬性值的對象就可以接收到。而如果使用application/json,則表示将前端的資料以序列化過的json傳遞到後端,後端要把它變成實體對象,還需要一個反序列化的過程。按照這個邏輯,那我們如果指定contentType為application/json,然後傳遞序列化過的對象應該也是可以的啊。部落客好奇心重,還是打算一試到底,于是就有了下面的代碼:

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

嘗試成功,也就是說,兩種寫法都是可行的。如果你指定了contentType為application/json,則必須要傳遞序列化過的對象;如果使用post請求的預設參數類型,則前端直接傳遞json類型的對象即可。 

有些時候,我們需要将基礎類型和實體一起傳遞到背景,這個時候,我們神奇的dynamic又派上用場了。

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

原理也不用多說,同上。

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結
C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

上面寫了那麼多,都是通過前端的ajax請求去做的,我們知道,如果調用方不是web項目,比如Android用戶端,可能需要從背景發送http請求來調用我們的接口方法,如果我們通過背景去發送請求是否也是可行的呢?我們以實體對象作為參數來傳遞寫寫代碼試一把。

當代碼運作到request.GetResponse()這一句的時候,API裡面進入斷點

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

嘗試成功。

WebApi裡面put請求一般用于對象的更新。它和用法和post請求基本相同。同樣支援[FromBody],同樣可以使用dynamic。

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

和post請求相同。

顧名思義,delete請求肯定是用于删除操作的。參數傳遞機制和post也是基本相同。下面簡單給出一個例子,其他情況參考post請求。

C#進階系列——WebApi 接口參數不再困惑:傳參詳解一、get請求二、post請求三、put請求四、delete請求五、總結

以上比較詳細的總結了WebApi各種請求的各種參數傳遞。每種情況都是部落客實際代碼測試過的,内容不難,但如果剛接觸這麼些東西還是需要一點時間去熟悉的,在此做個總結,希望能幫到剛剛接觸WebApi的園友們。如果本文能幫到你,不妨推薦下,您的推薦是部落客繼續總結的動力!

最近打算做點自己的東西出來,将部落格裡面的一些好的技術融合進去。有項目合作的小夥伴趕快聯系部落客吧!

歡迎各位轉載,但是未經作者本人同意,轉載文章之後必須在文章頁面明顯位置給出作者和原文連接配接,否則保留追究法律責任的權利!