最近悟出來一個道理,在這兒分享給大家:學曆代表你的過去,能力代表你的現在,學習代表你的将來。
十年河東十年河西,莫欺少年窮。
學無止境,精益求精
上一節講述了C# WebApi傳參之Get請求-AJAX
本節講述C# WebApi傳參之Post請求-AJAX,說起Ajax針對webApi的Post請求,真的不敢恭維,确實比較怪異,如果你不幸要寫一個Ajax Post請求webApi接口,那麼您還是有必要花點時間看看本篇部落格,如果你也遇到了同樣的問題,就不妨在最後給本篇部落格點個贊。謝謝
說起Post請求,想必大家都比較熟悉,post請求原理和get請求不一樣,我們知道get請求的參數是通過url來傳遞的,而post請求則是通過http的請求體中傳過來的,WebApi的post請求也需要從http的請求體裡面去取參數。說白了Get請求是通過URL傳遞一組鍵值對,Post請求是發送一個Http請求體。上一節Get請求,我們用到了[FromUri]關鍵字。本節的Post請求,我們将使用另一個關鍵字[FromBoay],上一節結尾我建議大家Get請求時要帶上[FromUri]關鍵字,同理,本節的Post請求,我要建議大家在接收參數時,帶上[FromBody]關鍵字,畢竟養成一個好的習慣不是什麼壞事。
開篇中提到,Ajax Post請求webApi很怪異,那麼它究竟怎麼怪異呢?下面以代碼示範說明:<本文仍舊采用上一節Get請求的實體對象,不知道的博友,請參閱我的上篇部落格>
如下:
/// <summary>
/// 簡單測試案例
/// </summary>
/// <returns></returns>
[HttpPost]
public string Get()
{
return "OK";
}
/// <summary>
/// 通過id擷取特定資料
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
[HttpPost]
public string GetById([FromBody]int Id)
{
list = list.Where(p => p.Id == Id).ToList();
return JsonHelper.JsonSerializer<List<Person>>(list);
}
aJax如下
//無參數請求-簡單示例
$(document).ready(function () {
$.ajax({
url: "http://localhost:9953/api/Person/Get",
type: "post",
contentType: "application/json",
dataType: "text",
data:{},
success: function (result,status) {
if (status == "success") {
alert(result);
}
},
error: function (error) {
alert(error);
}
});
});
//單個參數傳遞- data: {"":"3"}, 這種方式也竟然正确
$(document).ready(function (data) {
$.ajax({
url: "http://localhost:9953/api/Person/GetById",
type: "post",
contentType: "application/json",
dataType: "text",
data: {Id:"3"},
success: function (result,status) {
alert(result)
},
error: function (error) {
alert(error);
}
});
});
上文JS中注釋有這麼一句話:‘data: {"":"3"}, 這種方式也竟然正确’
這是一種另許多人頭痛的寫法,但是沒辦法,經過測試,這種寫法确實很正确。
根據上述案例,我們看到了Post請求傳遞單個參數的寫法,那麼如果傳遞多個參數,我們能否采取如下的方法?(經測試,如下寫法是錯誤的,報404Not Found)
$(document).ready(function (data) {
$.ajax({
url: "http://localhost:9953/api/Person/GetByIdAndSex",
type: "post",
contentType: "application/json",
dataType: "text",
data: { Id: "3",Sex:"W" },
success: function (result, status) {
alert(result)
},
error: function (error) {
alert(error);
}
});
});
/// <summary>
/// 錯誤的寫法 當然,本篇隻講解Ajax請求,如果你是通過HttpwebClient的方式進行請求,這種寫法是沒有任何問題的
/// </summary>
/// <param name="Json"></param>
/// <returns></returns>
[HttpPost]
public HttpResponseMessage GetByIdAndSex([FromBody]string Id,[FromBody]string Sex)
{
List<Person> list_2 = new List<Person>();
var Result = from r in list
where r.Id == Convert.ToInt32(Id) && r.Sex == Sex
select r;
foreach (var Item in Result)
{
list_2.Add(Item);
}
return ResultToJson.toJson(list_2);
}
測試的結果是:擷取不到Id 和 Sex 的值!開篇我們說到,Get的請求方式是通過URL傳遞鍵值對,而Post 請求傳遞的是一個Http請求體,而JS中 data: { Id: "3",Sex:"W" }, 采用的是鍵值對類型,而Post請求是不能讀取鍵值對滴。故:上述寫法不對。
那麼,你可能會問,為什麼一個參數請求的時候沒有問題,為什麼兩個參數就不行了呢?這個...我能作的解答是:這就是Post Ajax請求的怪異之處。
正确的寫法該當如何呢?
我們知道:Get請求傳遞兼職對,Post請求傳遞的是Http的請求體,按照本人的了解就是:Post請求需要發送一個參數作為Http請求體,這個參數為一個整體,而非一組鍵值對、故而,我們作如下改動:
代碼如下:
//多個參數傳遞
$(document).ready(function (data) {
$.ajax({
url: "http://localhost:9953/api/Person/GetByIdAndSex",
type: "post",
contentType: "application/json",
dataType: "text",
data: JSON.stringify({ Id: "3",Sex:"W" }),
success: function (result, status) {
alert(result)
},
error: function (error) {
alert(error);
}
});
});
/// <summary>
/// 錯誤的寫法2 怪異吧
/// </summary>
/// <param name="Json"></param>
/// <returns></returns>
[HttpPost]
public HttpResponseMessage GetByIdAndSex([FromBody]string Json)
{
string Id = JsonHelper.GetJsonValue(Json, "Id");//擷取Id
string Sex = JsonHelper.GetJsonValue(Json, "Sex");//擷取sex
List<Person> list_2 = new List<Person>();
var Result = from r in list
where r.Id == Convert.ToInt32(Id) && r.Sex == Sex
select r;
foreach (var Item in Result)
{
list_2.Add(Item);
}
return ResultToJson.toJson(list_2);
}
如上注釋為紅色加粗的JS代碼,我們将Post的鍵值對轉化為Json字元串傳遞到後端。而後端代碼中,我們嘗試接收這個JSon字元串,并作解析,從中讀出Id和Sex的值,按照Post請求規則,我們也是隻發送了一個Http請求體,并且在後端作了接收。這次應該沒有問題了吧?
實際測試的結果是:不會發生404 Not Found 錯誤,但是接收不到Post的字元串,也就是 [FromBody]string Json 中的Json為Null,(⊙o⊙)…
靠,這樣都不行,那到底怎麼能行呢?
下班了,不多噴了,直接告訴大家幾點注意事項:
後端接收時,參數類型應采用dynamic,JS代碼中,必須加上contentType對應的類型,Post的值必須為一個整體,而不能是鍵值對。JS中Type類型必須為Post ,後端接收類型必須為:[HttpPost],如果不加,則會預設為[HttpGet]方式。
以下是代碼示例,希望能幫助大家:
1、多個參數傳遞:
//多個參數傳遞
$(document).ready(function (data) {
$.ajax({
url: "http://localhost:9953/api/Person/GetByIdAndSex",
type: "post",
contentType: "application/json",
dataType: "text",
data: JSON.stringify({ Id: "3",Sex:"W" }),
success: function (result, status) {
alert(result)
},
error: function (error) {
alert(error);
}
});
});
[HttpPost]
public HttpResponseMessage GetByIdAndSex([FromBody]dynamic Json)
{
string Id = Json.Id;
string Sex = Json.Sex;
List<Person> list_2 = new List<Person>();
var Result = from r in list
where r.Id == Convert.ToInt32(Id) && r.Sex == Sex
select r;
foreach (var Item in Result)
{
list_2.Add(Item);
}
return ResultToJson.toJson(list_2);
}
2、傳遞一個對象資料
//傳遞對象數組
$(document).ready(function (data) {
var dataList = [{ Id: "8888", Sex: "男", Name: "陳卧龍", Age: "26" },
{ Id: "8887", Sex: "男", Name: "陳大龍", Age: "27" },
{ Id: "8886", Sex: "男", Name: "陳小龍", Age: "25" }];
$.ajax({
url: "http://localhost:9953/api/Person/GetByObjectList",
type: "post",
contentType: "application/json",
dataType: "text",
data: JSON.stringify(dataList),
success: function (result, status) {
alert(result)
},
error: function (error) {
alert(error);
}
});
});
/// <summary>
/// 對象數組作為參數
/// </summary>
/// <param name="P"></param>
/// <returns></returns>
[HttpPost]
public HttpResponseMessage GetByObjectList([FromBody]dynamic Plist)
{
List<Person> list = new List<Person>();
foreach (var item in Plist)
{
Person person = new Person()
{
Name = item.Name,
Sex = item.Sex,
Id = item.Id,
Age = item.Age,
};
list.Add(person);
}
return ResultToJson.toJson(list);
}