C# WebApi 接口传参解惑
正文
在学习WebApi时遇到了许多困惑,现记载并解惑。本文通过Get/Post/Put/Delete四种请求方式的传参。
Get请求传递参数
- Get请求的特性
- 如果Action前缀是Get则默认为Get请求方法
- 如果Action前缀不存在Get,那么就算服务器找到Aciton,也会返回405错误,因为不能确定请求方式。因此,这种情况下请标记请求方式。 日常使用中最常用的就是Get请求了。
1.基础类型
[HttpGet]
[Route("GetRes")]
public IHttpActionResult GetRes(int id ,int name)
{
return Ok();
}
$("#fr").on("submit", function (e) {
$.ajax({
type: "get",
url: "/api/Student/GetRes",
data: {id:1,name:20},
}).done(function () {
console.log("成功了");
}).fail(function () {
console.log("失败了");
});
})
基础类型的参数传递我们无需多说,通过查询字符串绑定参数
2.实体类型
/// <summary>
/// 实体类型
/// </summary>
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public DateTime DateTime { get; set; }
}
[HttpGet]
[Route("GetEntity")]
public IHttpActionResult GetEntity(Student student)
{
return Ok();
}
$("#fr").on("submit", function (e) {
e.preventDefault();
$.ajax({
type: "get",
url: "/api/Student/GetEntity",
contentType:"application/json",
data: { Name: "huangwei", Age: 20, DateTime: "2020-12-11" },
}).done(function () {
console.log("成功了");
}).fail(function () {
console.log("失败了");
});
})
如上图所示,如果我们直接将json对象传递给后台,后台无法接受到这个对象,但确实调用了这个Action。为什么会造成这种结果?
原因在于,我们通过get请求的时候,数据是通过附加在url中传递到后台的。因此,json对象属性key/value附加到了url中,然而后台action中参数列表又没有与之对应,因此参数为null。
我们可以使用FromUri特性标记参数,即可从QueryString中获取数据进行模型绑定
2.Post请求
WebApi中,Post请求一般用于提交数据
1.基础数据类型
post请求与get请求传递参数的方式是有区别的,get请求参数存放于QueryString中,而post请求传递的参数存放于http请求体中。在webApi中,post请求传递参数同样需要放于http方法体中。
错误的做法:且前台返回404状态码
[HttpPost]
[Route("PostName")]
public IHttpActionResult PostName(string name)
{
return Ok();
}
$("#fr").on("submit", function (e) {
e.preventDefault();
$.ajax({
type: "post",
url: "/api/Student/PostName",
data:{ name: "huangwei" },
}).done(function () {
console.log("成功了");
}).fail(function () {
console.log("失败了");
});
})
正确的做法
[HttpPost]
[Route("PostName")]
public IHttpActionResult PostName([FromBody]string name)
{
return Ok();
}
$("#fr").on("submit", function (e) {
e.preventDefault();
$.ajax({
type: "post",
url: "/api/Student/PostName",
data:{ "": "huangwei" },
}).done(function () {
console.log("成功了");
}).fail(function () {
console.log("失败了");
});
})
通常我们通过url去参数是key = value 的方式取出,然而webApi中 post请求的参数标记FromBody特性后,并不能通过key = value 的方式获取数据,他没有key。如果在这里写了key那么获得的参数为null。
如果我们在多个基础类型的情况下,我们该怎么办?注意一个Action中只能存在一个FromBody特性,方法如下:
[HttpPost]
[Route("POne")]
public IHttpActionResult POne(dynamic argument)
{
var name = argument.name;
var age = argument.age;
return Ok();
}
$("#fr").on("submit", function (e) {
e.preventDefault();
$.ajax({
type: "post",
url: "/api/Student/POne",
contentType: "application/json",
data: JSON.stringify({ name: "huangwei", age: "20" }),
}).done(function () {
console.log("成功了");
}).fail(function () {
console.log("失败了");
});
})
使用dynamic 类型省略掉了[FromBody],但我们必须要注意调用属性的一致性,
在ajax中还需要注意,contentType:"application/json",表示参数类型是json
2.实体参数
[HttpPost]
[Route("LogIn")]
public IHttpActionResult LogIn([FromBody]UserModel userModel)
{
return Ok();
}
$("#fr").on("submit", function (e) {
e.preventDefault();
let data = $(this).serializeArray();
let obj = {};
$.each(data, function (index, val) {
obj[val.name] = val.value
})
$.ajax({
url: "/api/Student/LogIn",
type: "post",
data: obj,
}).done(function (data) {
console.log("成功了")
}).fail(function () {
console.log("失败了")
})
})
单个实体参数时后台可以使用FromBody,也可以不使用
如果使用 contentType:"application/json",那么必须使用JSON.stringify(data)将数据转换为JSON字符串的形式。如果不指定contentType:"application/json",那么就不能使json字符串传递参数 原理解释:我们来看看它默认的contentType是什么:
- application/x-www-form-urlencoded : <from encType = "">中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认提交数据的格式)
- application/json : JSON数据格式 也就是说post请求默认是将表单里面的数据的key/value形式发送到服务,而我们的服务器只需要有对应的key/value属性值的对象就可以接收到。而如果使用application/json,则表示将前端的数据以序列化过的json字符串形式传递到后端,后端要把它变成实体对象。
[HttpPost]
[Route("LogIn")]
public IHttpActionResult LogIn([FromBody]UserModel userModel)
{
return Ok();
}
$("#fr").on("submit", function (e) {
e.preventDefault();
let data = $(this).serializeArray();
let obj = {};
$.each(data, function (index, val) {
obj[val.name] = val.value
})
$.ajax({
url: "/api/Student/LogIn",
type: "post",
data: JSON.stringify(obj),
contentType: "application/json"
}).done(function (data) {
console.log("成功了")
}).fail(function () {
console.log("失败了")
})
})
3. 数组参数
- 基础类型
[HttpPost]
public bool SaveData(string[] ids)
{
return true;
}
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(List<TB_CHARGING> lstCharging)
{
return true;
}
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) {}
});
put和delete传参基本与 post请求一致