$.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); } } });
[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; }
這樣在后台得到我們序列化過的對象,再通過反序列化就能得到對象。
數組作為參數
一般get請求不建議將數組作為參數,因為我們知道get請求傳遞參數的大小是有限制的,最大1024字節,數組里面內容較多時,將其作為參數傳遞可能會發生參數超限丟失的情況。
$.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; }
方法名以Get開頭,WebApi會自動默認這個請求就是get請求,而如果你以其他名稱開頭而又不標注方法的請求方式,那么這個時候服務器雖然找到了這個方法,但是由於請求方式不確定,所以直接返回給你405——方法不被允許的錯誤。
最后結論:所有的WebApi方法最好是加上請求的方式([HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]),不要偷懶,這樣既能防止類似的錯誤,也有利於方法的維護,別人一看就知道這個方法是什么請求。
二、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', 這個屬性。
通過上文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; }
博文的一點評論:
dynamic雖然很巧妙地解決了從請求body中獲取參數。但是這樣不利於生成api文檔。
ps:一般都是用pagehelp等工具,自動讀取元數據,生成api文檔的。
如果用dynamic的話,生成的文檔就只有一個dynamic類型的參數,這樣api調用者就無法明確api的參數了。
還有接收參數定義為dynamic類型的話,后續維護或升級太麻煩。
如果是post操作。文中介紹了兩種傳遞實體參數的方法
第一種:
1
|
data: { ID:
"1"
, NAME:
"Jim"
, CREATETIME:
"1988-09-11"
}
|
不需要指定contentType。
第二種:
1
|
data:
"{\"SoldToParty\":\"fdsfds\",\"SaleOrg\":\"fdsfds\",\"Channel\":\"ffffff\",\"Division\":\"dfdfsdsfd\"}"
|
需要指定contentType:"application/json"。兩種方式后台都可以得到實體。不知道你的Json字符串是怎么得到的,是拼的字符串?建議使用JSON.stringify( { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" })這種方式得到json字符串。
HttpPost傳單個變量
[HttpPost]
public JsonResult DeleteFrequencyInfo(List<string> ids)
$.ajax(
{
url: "/Frequency/DeleteFrequencyInfo",
type: "post",
data: { "ids": deleted },
dataType: "json",
HttpPost傳實體
[HttpPost]
public JsonResult GetFrequencyPrint(FrequencyPrintQO request)
public class FrequencyPrintQO
{
public string FrequencyId { get; set; }
public List<string> Freedombarcodes { get; set; }
}
$.ajax({
type: "POST",
url: '/Print/GetFrequencyPrint',
dataType: "Json",
async: false, // 此處必須定義為同步
data: {Freedombarcodes: freedombarcodes},
參考:http://www.cnblogs.com/landeanfen/p/5337072.html