1. 程式人生 > >【WebApi系列】詳解WebApi如何傳遞參數

【WebApi系列】詳解WebApi如何傳遞參數

學習 路由規則 體系結構 fff 基本數據類型 xxx work 版權 小結

WebApi系列文章

【01】淺談HTTP在WebApi開發中的運用

【02】聊聊WebApi體系結構

【03】詳解WebApi參數的傳遞

【04】詳解WebApi測試和PostMan

【05】淺談WebApi Cores

【06】詳解WebApi 異常處理

【07】用WebAPI寫個基於EF的CURD

【08】淺談WebAPI身份認證

【09】詳解系列化和模型綁定

【10】淺談WebApi如何配合Mvc有效工作

【11】淺談API Reference

【12】淺談接口在軟件架構中的作用

【13】淺談WebApi和WebService的比較

【14】淺談如何設計一個良好的接口

技術分享圖片


閱讀目錄

一 概述

二 Get

1 基礎數據類型

1.1 方法只含一個形參

1.2 方法含多個形參

2 實體對象類型

3 實體對象和基礎數據類型混合

4 最小滿足原則

5 url長度限制

6 Get規範化

7 關於實體作為參數傳遞的拓展

7.1 借助[FromUri]特性傳遞實體

7.2 系列化和反系列化傳遞實體

三 Post

1 基本數據類型傳遞

1.1 [FromBody]單個參數傳遞


1.2 Dynamic單個參數傳遞

2 實體作為參數傳遞

3 實體集合作為參數傳遞

4 數組作為參數傳遞

5 小結

四 總結

一 概述

一般地,我們在研究一個問題時,常規的思路是為該問題建模;我們在研究相似問題時,常規思路是找出這些問題的共性和異性。基於該思路,我們如何研究WebApi參數傳遞問題呢?

首先,從參數本身來說,種類較為多(如int,double,float,string,array,Object等),且有些類型較為復雜(如值類型和引用類型的機制等);

其次,從基於WebApi的Http請求方法來說,種類多且不盡相同(如Get,post,Delete,put,head等),在上一篇文章 :【WebApi系列】淺談HTTP在WebApi開發中的運用 中,我們簡要描述了Http請求的20個方法;

..........

如此復雜且不盡相同,關於WebApi參數傳遞,我們該選擇什麽作為切入點來研究呢?基於我們上面提到的研究思路,我們想到了.NET Framework框架,那麽,我們來看看基於.NET Framework框架的的WebApi

模板是怎樣的呢?

請按圖中步驟操作

技術分享圖片

我們來看看Values控制器是怎樣的

 1  public class ValuesController : ApiController
 2     {
 3         // GET api/values
 4         public IEnumerable<string> Get()
 5         {
 6             return new string[] { "value1", "value2" };
 7         }
 8 
 9         // GET api/values/5
10         public string Get(int id)
11         {
12             return "value";
13         }
14 
15         // POST api/values
16         public void Post([FromBody]string value)
17         {
18         }
19 
20         // PUT api/values/5
21         public void Put(int id, [FromBody]string value)
22         {
23         }
24 
25         // DELETE api/values/5
26         public void Delete(int id)
27         {
28         }
29     }

從Values控制器,我們不難得出如下幾個結論:

(1)WebApi常規方法為四個:Get,Post,Put和Delete;

(2)四種方法的參數可歸結為兩大類:url傳遞(Request-url)和Body(Request-body)傳遞;

(3)基於(2),我們將四種方法的參數傳遞歸為兩大類,而這兩大類又集中在Get和Post中體現了(Put是Get和Post的組合,Delete與Get類似);

其實,分析到現在,我們很容易找得到了研究WebApi參數傳遞的切入點?研究Get和Post方法參數傳遞即可。是的,沒錯,我們本篇文章就是基於Get和Post方法的參數傳遞,前者對應Request-url,後者對應Reqeust-Body。

二 Get

1 基礎數據類型


1.1 方法只含一個形參(參數傳得進去)

ajax

$(document).ready(function () {
   $("#FindProdcutDetail").click(function () {
       $.ajax({
               type: "Get",
               //url: "/api/Default/GetProductDetails?ProductCode=JX80869"
               url: "/api/Default/GetProductDetails",
               data: { "ProductCode":"JX80869"}
            })
        })           
   })

Result

技術分享圖片

總結

(1)當Get方法形參為一個且為基本數據類型時,Get方法能接受外部傳遞的值

(2)Get傳值的本質是通過url字符串拼接,如上兩兩種url形式的傳遞的結果都是一樣

url形式1

url: "/api/Default/GetProductDetails?ProductCode=JX80869"

url形式2

url: "/api/Default/GetProductDetails",
data: { "ProductCode":"JX80869"}

我們用Goole Chrome來看看結果,發現url形式1和url形式2均一致

技術分享圖片

(3)Get傳遞參數本質是url字符串拼接,Request-Head頭部傳遞,Request-Body中不能傳遞(這是與Post方法的本質區別),我們舉兩個例子

例子1:我們將形參添加[FromBody]屬性後,值傳遞不進去

技術分享圖片

例子2:我們用PostMan來測試,發現PostMan中,Get方法參數Body為灰色,是不能選中的

技術分享圖片

1.2 方法含有多個形參(參數傳得進去)

$(document).ready(function () {
   $("#FindProdcutDetail").click(function () {
      $.ajax({
               type: "Get",
               url: "/api/Default/GetProductDetails",
               data: { "ProductCode": "JX80869","ProductName":"YaGao"}
            })
        })
  })

result

技術分享圖片

2 實體對象類型(參數傳不進去)


model

 1  public class ProductDetail
 2     {
 3         //產品編碼
 4         [Required]
 5         public string ProductCode { get; set; }
 6         //產品名稱
 7         [Required]
 8         public string ProductName { get; set; }
 9         //產品價格
10         [Required]
11         public double  ProductPrice{ get; set; }
12     }

ajax

$(document).ready(function () {
    var productDetail = { "ProductName": "YaGao", "ProductCode": "JX80869", "ProductPrice": 40.5};
        $("#FindProdcutDetail").click(function () {
            $.ajax({
                    type: "Get",
                    url: "/api/Default/ProductDetails",
                    data: productDetail
                })
            })
        })

result:

技術分享圖片

分析

技術分享圖片

3 實體對象和基礎數據類型混合(實體傳不進去,基礎數據能傳遞進去)


ajax

1 $(document).ready(function () {
2    $("#FindProdcutDetail").click(function () {
3        $.ajax({
4                 type: "Get",
5                 url: "/api/Default/GetProductDetails",
6                 data: { "_productDetail": "ObjectEntity","ProductName":"YaGao"}
7              })
8         })
9     })

result

技術分享圖片

4 最小滿足原則(參數傳得進去)


所謂“最小滿足原則”,指外部參數必須至少滿足被調用方法的形參(形參個數,形參類型和形參名字),換句話說,被調用方法具有的形參,外部參數必須傳遞進來,被調用方法沒有

的形參,外部參數傳遞與否都可以,否則將會產生狀態碼404錯誤,用數學集合的思路來理解的話,被調用方法的形參相當於外部參數的子集。如下例子,我們舉一個真子集的例子,

即外部傳遞參數的個數大於被調方法的的形參個數。

Ajax

 $(document).ready(function () {
    $("#FindProdcutDetail").click(function () {
       $.ajax({
                type: "Get",
                url: "/api/Default/GetProductDetails",
                data: {"ProductCode": "JX00034", "ProductName": "YaGao", "ProductPrice": 20.5, "PrudcutType": "Daily Necessities"}
                })
            })
        })

result

技術分享圖片

分析:主要原因是路由規則,路由從url裏面取參數與aciton參數匹配,直到匹配滿足為止,具體詳細深入內容,在【WebApi系列】路由章節分析。

技術分享圖片

5 url長度限制


url參數長度是有一定限制的,當超過一定長度,會報404錯誤

ajax

 $(document).ready(function () {
            $("#FindProdcutDetail").click(function () {
                $.ajax({
                    type: "Get",
                    url: "/api/Default/GetProductDetails",
                    data: {
                        "ProductCode":
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                        "JX00034xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 
                    }
                })
            })
        })

result

技術分享圖片

6 Get規範化


關於Get類型規範化,應註意兩點,避免不必要的錯誤或異常:(1)方法的命名盡量采用:“Get+方法名”的形式 (2)在每個方法上加上特性[HttpGet]。

技術分享圖片

例子:我們去掉[HttpGet]特性和方法前的Get,看看情況什麽怎樣的

ajax

$(document).ready(function () {
    $("#FindProdcutDetail").click(function () {
        $.ajax({
                 type: "Get",
                 url: "/api/Default/ProductDetails",
                 data: {"ProductCode": "JX00034 "}
             })
         })
    })

Controller

1 public class DefaultController : ApiController
2     {
3         4         //[HttpGet]
5         public string ProductDetails(string ProductCode)
6         {
7             return "values";
8         }
9     }

Result

技術分享圖片

7 關於實體作為參數傳遞的拓展


7.1 借助[FromUri]特性傳遞實體

ajax

$(document).ready(function () {
   var GetEntityParam = { "ProductName": "YaGao", "ProductCode": "JX80869", "ProductPrice": 40.5};
      $("#FindProdcutDetail").click(function () {
        $.ajax({
                 type: "Get",
                 url: "/api/Default/ProductDetails",
                 data: GetEntityParam
               })
           })
      })

result

技術分享圖片

7.2 系列化與反系列化傳遞實體

ajax

$(document).ready(function () {
   $("#FindProdcutDetail").click(function () {
       $.ajax({
                type: "Get",
                url: "/api/Default/ProductDetails",
                data: { "productDetail": JSON.stringify({ "ProductName": "YaGao", "ProductCode": "JX80869", "ProductPrice": 40.5 }) }
             })
         })
     })

result

技術分享圖片

8 小結


(1)Get參數傳遞的本質是url字符串拼接;

(2)url字符串長度受限制;

(3)Get參數傳遞在Http請求頭部傳遞,而不支持Request-Body傳遞;

(4)Get類型的方法支持參數為基本類型,不支持實體類型;

(5)Get類型的方法命名,應盡量采用“Get+方法名”的命名方式,且習慣性地在方法前加上[HttpGet特性];

(6)實參與形參的匹配,遵循路由規則;

(7)Get對應DB的Select操作,從這一點來理解,就知道為什麽Http不支持實體對象傳遞的合理性了,因為一般情況,我們都是通過簡單的字段查詢信息(對應基本類型),

如ID號,用戶名等,而不會通過一個實體查詢數據;

三 Post

1 基本數據類型傳遞


1.1 [FromBody]單個參數傳遞

ajax

技術分享圖片

result

技術分享圖片

1.2 dynamic單個參數傳遞

ajax

$(document).ready(function () {
   $("#FindProdcutDetail").click(function () {
      $.ajax({
               type: "Post",
               contentType: ‘application/json‘,
               url: "/api/Default/PostParamToProducts",
               data: JSON.stringify({"ProductCode":"JX00039"})
           })
       })
   })

result

技術分享圖片

Googel Chrome查看

技術分享圖片

2 實體作為參數傳遞


ajax

$(document).ready(function () {
   $("#FindProdcutDetail").click(function () {
      $.ajax({
               type: "Post",
               url: "/api/Default/PostParamToProducts",
               data: { "ProductCode": "JX00036","ProductName":"YaGao","ProductPrice":20.5}
            })
        })
    })

result

技術分享圖片

我們用Googel Chrome看看

技術分享圖片

3 實體集合作為參數傳遞


ajax

$(document).ready(function () {
   var list_ProductDetail = [
       { "ProductCode": "JX00031", "ProductName": "ToothPaste", "ProductPrice": "20.5" },
       { "ProductCode": "JX00032", "ProductName": "ToothBrush ", "ProductPrice": "18.9" },
       { "ProductCode": "JX00033", "ProductName": "Pen", "ProductPrice": "199.9" },
       { "ProductCode": "JX00034", "ProductName": "computer", "ProductPrice": "15000.5" }
       ]
   $("#FindProdcutDetail").click(function () {
   $.ajax({
             type: "Post",
             contentType: ‘application/json‘,
             url: "/api/Default/PostParamToProducts",
              data: JSON.stringify(list_ProductDetail)
          })
      })
  })

result

技術分享圖片

Google Chrome 查看

技術分享圖片

4 數組作為參數傳遞


ajax

$(document).ready(function () {
   var arr = ["a", "b", "c", "d"];
   $("#FindProdcutDetail").click(function () {
      $.ajax({
               type: "Post",
               contentType: ‘application/json‘,
               url: "/api/Default/PostParamToProducts",
               data: JSON.stringify(arr)
            })
       })
  })

Result

技術分享圖片

我們用Google Chrome看看

技術分享圖片

5 小結


(1)Post參數傳遞本事是在Request-Body內傳遞,而Get參數傳遞本質是url拼接;

(2)Post參數傳遞不是key/value形式,而Get參數是key/value形式;

(3)Post傳遞參數時,無論是單個參數還是對象,均借助[FromBody]特性(當然,某些情況去掉[FromBody]特性也可把值傳遞進去,但未了規範化,盡量加上該特性);

(4)Post沒長度限制,而Get有長度限制(一般為1024b);

(5)Post相對Get,較安全;

(6)Post操作相當於DB的Insert操作;

四 總結

1.雖然HTTP請求方法有20多種,常用的大致為4種,即Get,Post,Put,Delete(當然,像Trace,Head等也常用);

2.Get,Post,Put,Delete分別對應DB的Select,Insert,Update和Delete操作;

3.WebApi參數類型,大致分為基本數據類類型和對象數據類型(當然你也可以理解為抽象數據類型);

4.研究WebApi參數傳遞,只需研究Get和Post即可,因為其他http方法參數傳遞基本都是有這兩種組合而成(如Put有Get和Post組合而成),或者相似(如Delete與Get相似);

5.對於控制器方法,盡量參照規範格式寫,如在相應控制器方法上加上對應的htt請求(Get對應[HttpGet],Post對應[HttpPost]),方法名盡量采用“Http請類型+方法名”格式(如Get請求,建議采用Get+MethodName;Post請求對應Post+MethodName);

6.WebApi參數請求,大致分為兩大類型,即Request-url和Request-body;

7.文中我們還簡要分析了Get和Post區別;

8.關於如何設計一個良好的接口,在文章中,我們觸及了一下,但未研究,會在後續的文章中單獨分析;

五 版權區

  • 感謝您的閱讀,若有不足之處,歡迎指教,共同學習、共同進步。
  • 博主網址:http://www.cnblogs.com/wangjiming/。
  • 極少部分文章利用讀書、參考、引用、抄襲、復制和粘貼等多種方式整合而成的,大部分為原創。
  • 如您喜歡,麻煩推薦一下;如您有新想法,歡迎提出,郵箱:[email protected]
  • 可以轉載該博客,但必須著名博客來源。

【WebApi系列】詳解WebApi如何傳遞參數