<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
        

      C#進階系列——WebApi 接口參數不再困惑:傳參詳解

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

      WebApi系列文章

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

      一、get請求

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

      1、基礎類型參數

      [HttpGet]
      public string GetAllChargingData(int id, string name)
      {
          return "ChargingData" + id;
      }
      $.ajax({
              type: "get",
              url: "http://localhost:27221/api/Charging/GetAllChargingData",
              data: { id: 1, name: "Jim", bir: "1988-09-11"},
              success: function (data, status) {
                  if (status == "success") {
                      $("#div_test").html(data);
                  }
              }
          });

      參數截圖效果

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

      2、實體作為參數

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

          public class TB_CHARGING
          {
              /// <summary>
              /// 主鍵Id
              /// </summary>
              public string ID { get; set; }
      
              /// <summary>
              /// 充電設備名稱
              /// </summary>
              public string NAME { get; set; }
      
              /// <summary>
              /// 充電設備描述
              /// </summary>
              public string DES { get; set; }
      
              /// <summary>
              /// 創建時間
              /// </summary>
              public DateTime CREATETIME { get; set; }
          }
      [HttpGet]
      public string GetByModel(TB_CHARGING oData)
      {
           return "ChargingData" + oData.ID;
      }
        $.ajax({
              type: "get",
              url: "http://localhost:27221/api/Charging/GetByModel",
              contentType: "application/json",
              data: { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" },
              success: function (data, status) {
                  if (status == "success") {
                      $("#div_test").html(data);
                  }
              }
          });

      測試結果

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

      原來,get請求的時候,默認是將參數全部放到了url里面直接以string的形式傳遞的,后臺自然接不到了。

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

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

          var postdata = { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" };
          $.ajax({
              type: "get",
              url: "http://localhost:27221/api/Charging/GetAllChargingData",
              data: postdata,
              success: function (data, status) { }
          });
              [HttpGet]
              public string GetAllChargingData([FromUri]TB_CHARGING obj)
              {
                  return "ChargingData" + obj.ID;
              }

      得到結果:

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

        $.ajax({
              type: "get",
              url: "http://localhost:27221/api/Charging/GetByModel",
              contentType: "application/json",
              data: { strQuery: JSON.stringify({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }) },
              success: function (data, status) {
                  if (status == "success") {
                      $("#div_test").html(data);
                  }
              }
          });
              [HttpGet]
              public string GetByModel(string strQuery)
              {
                  TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery);
                  return "ChargingData" + oData.ID;
              }

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

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

      至于還有園友們提到http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api的model binder這種方式,博主看了下,覺得略復雜。有興趣的也可以試試。至于用哪一種方式傳遞對象,園友們可以自行選擇。

      3、數組作為參數

      一般get請求不建議將數組作為參數,因為我們知道get請求傳遞參數的大小是有限制的,最大1024字節,數組里面內容較多時,將其作為參數傳遞可能會發生參數超限丟失的情況。

      4、“怪異”的get請求

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

      (1)WebApi的方法名稱以get開頭

          $.ajax({
              type: "get",
              url: "http://localhost:27221/api/Charging/GetByModel",
              contentType: "application/json",
              data: { strQuery: JSON.stringify({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }) },
              success: function (data, status) {
                  if (status == "success") {
                      $("#div_test").html(data);
                  }
              }
          });
              [HttpGet]
              public string GetByModel(string strQuery)
              {
                  TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery);
                  return "ChargingData" + oData.ID;
              }

      這是標準寫法,后臺加[HttpGet],參數正常得到:

      為了對比,我將[HttpGet]去掉,然后再調用

              //[HttpGet]
              public string GetByModel(string strQuery)
              {
                  TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery);
                  return "ChargingData" + oData.ID;
              }

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

      (2)WebApi的方法名稱不以get開頭

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

          $.ajax({
              type: "get",
              url: "http://localhost:27221/api/Charging/FindByModel",
              contentType: "application/json",
              data: { strQuery: JSON.stringify({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }) },
              success: function (data, status) {
                  if (status == "success") {
                      $("#div_test").html(data);
                  }
              }
          });
              [HttpGet]
              public string FindByModel(string strQuery)
              {
                  TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery);
                  return "ChargingData" + oData.ID;
              }

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

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

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

      博主的理解是:方法名以Get開頭,WebApi會自動默認這個請求就是get請求,而如果你以其他名稱開頭而又不標注方法的請求方式,那么這個時候服務器雖然找到了這個方法,但是由于請求方式不確定,所以直接返回給你405——方法不被允許的錯誤。

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

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

      二、post請求

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

      1、基礎類型參數

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

      (1)錯誤的寫法

          $.ajax({
              type: "post",
              url: "http://localhost:27221/api/Charging/SaveData",
              data: { NAME: "Jim" },
              success: function (data, status) {
                  if (status == "success") {
                      $("#div_test").html(data);
                  }
              }
          });
              [HttpPost]
              public bool SaveData(string NAME)
              {
                  return true;
              }

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

      (2)正確的用法

          $.ajax({
              type: "post",
              url: "http://localhost:27221/api/Charging/SaveData",
              data: { "": "Jim" },
              success: function (data, status) {}
          });
              [HttpPost]
              public bool SaveData([FromBody]string NAME)
              {
                  return true;
              }

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

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

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

      (1)錯誤寫法

          $.ajax({
              type: "post",
              url: "http://localhost:27221/api/Charging/SaveData",
              data: { "": "Jim","":"備注" },
              success: function (data, status) {}
          });
              [HttpPost]
              public bool SaveData([FromBody]string NAME, [FromBody] string DES)
              {
                  return true;
              }

      得到結果

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

      (2)正確用法

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

          $.ajax({
              type: "post",
              url: "http://localhost:27221/api/Charging/SaveData",
              contentType: 'application/json',
              data: JSON.stringify({ NAME: "Jim",DES:"備注" }),
              success: function (data, status) {}
          });
              [HttpPost]
              public object SaveData(dynamic obj)
              {
                  var strName = Convert.ToString(obj.NAME);
                  return strName;
              }

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

      (3)推薦用法

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

      2、實體作為參數

      (1)單個實體作為參數

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

          $.ajax({
              type: "post",
              url: "http://localhost:27221/api/Charging/SaveData",
              data: { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" },
              success: function (data, status) {}
          });
              [HttpPost]
              public bool SaveData(TB_CHARGING oData)
              {
                  return true;
              }

      得到結果

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

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

      • application/x-www-form-urlencoded : <form encType=””>中默認的encType,form表單數據被編碼為key/value格式發送到服務器(表單默認的提交數據的格式);
      • application/json    : JSON數據格式

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

          var postdata = { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" };
          $.ajax({
              type: "post",
              url: "http://localhost:27221/api/Charging/SaveData",
              contentType: 'application/json',
              data: JSON.stringify(postdata),
              success: function (data, status) {}
          });
              [HttpPost]
              public bool SaveData(TB_CHARGING lstCharging)
              {
                  return true;
              }

      得到結果:

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

      (2)實體和基礎類型一起作為參數傳遞

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

          var postdata = { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" };
          $.ajax({
              type: "post",
              url: "http://localhost:27221/api/Charging/SaveData",
              contentType: 'application/json',
              data: JSON.stringify({ NAME:"Lilei", Charging:postdata }),
              success: function (data, status) {}
          });
              [HttpPost]
              public object SaveData(dynamic obj)
              {
                  var strName = Convert.ToString(obj.NAME);
                  var oCharging = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(Convert.ToString(obj.Charging));
                  return strName;
              }

      得到結果:

      原理也不用多說,同上。

      3、數組作為參數

      (1)基礎類型數組

          var arr = ["1", "2", "3", "4"];
          $.ajax({
              type: "post",
              url: "http://localhost:27221/api/Charging/SaveData",
              contentType: 'application/json',
              data: JSON.stringify(arr),
              success: function (data, status) { }
          });
              [HttpPost]
              public bool SaveData(string[] ids)
              {
                  return true;
              }

      得到結果:

      (2)實體集合

          var arr = [
              { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" },
              { ID: "2", NAME: "Lilei", CREATETIME: "1990-12-11" },
              { ID: "3", NAME: "Lucy", CREATETIME: "1986-01-10" }
          ];
          $.ajax({
              type: "post",
              url: "http://localhost:27221/api/Charging/SaveData",
              contentType: 'application/json',
              data: JSON.stringify(arr),
              success: function (data, status) {}
          });
              [HttpPost]
              public bool SaveData(List<TB_CHARGING> lstCharging)
              {
                  return true;
              }

      得到結果:

      4、后臺發送請求參數的傳遞

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

          public void TestReques()
          {
               //請求路徑
                  string url = "http://localhost:27221/api/Charging/SaveData";
      
                  //定義request并設置request的路徑
                  WebRequest request = WebRequest.Create(url);
                  request.Method = "post";
      
                  //初始化request參數
                  string postData = "{ ID: \"1\", NAME: \"Jim\", CREATETIME: \"1988-09-11\" }";
      
                  //設置參數的編碼格式,解決中文亂碼
                  byte[] byteArray = Encoding.UTF8.GetBytes(postData);
      
                  //設置request的MIME類型及內容長度
                  request.ContentType = "application/json";
                  request.ContentLength = byteArray.Length;
      
                  //打開request字符流
                  Stream dataStream = request.GetRequestStream();
                  dataStream.Write(byteArray, 0, byteArray.Length);
                  dataStream.Close();
      
                  //定義response為前面的request響應
                  WebResponse response = request.GetResponse();
      
                  //獲取相應的狀態代碼
                  Console.WriteLine(((HttpWebResponse)response).StatusDescription);
      
                  //定義response字符流
                  dataStream = response.GetResponseStream();
                  StreamReader reader = new StreamReader(dataStream);
                  string responseFromServer = reader.ReadToEnd();//讀取所有
                  Console.WriteLine(responseFromServer);
          }

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

      嘗試成功。

      三、put請求

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

      1、基礎類型參數

          $.ajax({
              type: "put",
              url: "http://localhost:27221/api/Charging/Update",
              contentType: 'application/json',
              data: JSON.stringify({ ID: "1" }),
              success: function (data, status) {}
          });
              [HttpPut]
              public bool Update(dynamic obj )
              {
                  return true;
              }

      2、實體作為參數

      和post請求相同。

      3、數組作為參數

      和post請求相同。

      四、delete請求

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

          var arr = [
              { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" },
              { ID: "2", NAME: "Lilei", CREATETIME: "1990-12-11" },
              { ID: "3", NAME: "Lucy", CREATETIME: "1986-01-10" }
          ];
          $.ajax({
              type: "delete",
              url: "http://localhost:27221/api/Charging/OptDelete",
              contentType: 'application/json',
              data: JSON.stringify(arr),
              success: function (data, status) {}
          });
              [HttpDelete]
              public bool OptDelete(List<TB_CHARGING> lstChargin)
              {
                  return true;
              }

      五、總結

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

      最近打算做點自己的東西出來,將博客里面的一些好的技術融合進去。有項目合作的小伙伴趕快聯系博主吧!

      本文原創出處:http://www.rzrgm.cn/landeanfen/

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

       

      posted @ 2016-04-06 13:27  懶得安分  閱讀(290620)  評論(193)    收藏  舉報
      主站蜘蛛池模板: 国产精品中文字幕日韩| 日本公妇乱偷中文字幕| 夜夜爽77777妓女免费看| 成人国产av精品免费网| 亚洲天堂在线免费| 麻豆妓女爽爽一区二区三| 国产超碰人人爽人人做人人添| 国产亚洲色视频在线| 国产精品麻豆成人av电影艾秋| 亚洲熟妇自偷自拍另类| 亚洲午夜香蕉久久精品| 精品国产一区二区三区麻豆| 国产免费一区二区不卡| 丰满少妇在线观看网站| 国产中年熟女大集合| 国产黄大片在线观看画质优化| 国产精品白浆无码流出| 成人一区二区人妻不卡视频| 国产a在视频线精品视频下载| 久久国产免费直播| 国产综合色一区二区三区| 年轻女教师hd中字3| 精品 无码 国产观看| 中文有码字幕日本第一页| 伊人无码精品久久一区二区| av色国产色拍| 欧美激情一区二区| 六十路老熟妇乱子伦视频| 四虎库影成人在线播放| 国产日韩一区二区在线看| 亚洲韩欧美第25集完整版| 成人久久精品国产亚洲av| 亚洲国产精品午夜福利| 精品国产免费第一区二区三区 | 成人一区二区三区在线午夜| 久久精品国产只有精品96| 欧美人与zoxxxx另类| 国产蜜臀av在线一区二区| 国产熟睡乱子伦视频在线播放| 国产亚洲精品岁国产精品| 好爽毛片一区二区三区四|