前言:
.NET Core WebAPI 控制器中接收的参数一般情况下分为简单类型(int、string、double…)、实体类dto、数据集合类型。
事实上,http请求可以把请求参数放到 query、header、form、body 中,而 .NET Core WebAPI 中默认启用了推理规则,可以自动推理参数在哪里并传入控制器参数中。开启默认推理规则时,对于简单类型参数,不能推理出去哪里接收,需要将参数显示指定为 [FromForm] 或者 [FromBody] 等等。
1. 指定参数接收位置的特性
特性 | 绑定源 |
---|---|
[FromBody] | 请求正文 |
[FromForm] | 请求正文中的表单数据 |
[FromHeader] | 请求标头 |
[FromQuery] | 请求查询字符串参数 |
[FromRoute] | 当前请求中的路由数据 |
[FromServices] | 作为操作参数插入的请求服务 |
2. 默认规则下接收参数的方式
/// <summary>
/// 默认启用参数推理规则时
/// </summary>
[Route("api/[controller]/[action]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpPost]
public ActionResult AddFormPara1([FromForm]string id)
{
//application/x-www-form-urlencoded
//对于简单类型(string、int),推理不出来,所以需要显示指定参数来源FromForm
var context = HttpContext.Request;
return Ok(new { id = id });
}
[HttpPost]
public ActionResult AddFormPara([FromForm] string id, [FromForm] string name)
{
//application/x-www-form-urlencoded
//对于简单类型(string、int),推理不出来,所以需要显示指定参数来源FromForm
var context = HttpContext.Request;
return Ok(new { id = id, name = name });
}
[HttpPost]
public IActionResult AddJsonPara1([FromBody] string id)
{
//json格式请求过来时Request中的data直接就是id的值,例:data:"111"
var context = HttpContext.Request;
return Ok(new { id = id });
}
[HttpPost]
public ActionResult AddJsonPara(dto dto)
{
//application/json {"id":"111","name":"winston"}
var context = HttpContext.Request;
return Ok(new { id = dto.id, name = dto.name });
}
[HttpPost]
public ActionResult AddJsonParaList(List<dto> dto)
{
//application/json [{"id":"111","name":"winston"}]
var context = HttpContext.Request;
return Ok(dto);
}
//[HttpPost]
//public ActionResult AddJsonPara1([FromBody] string id, [FromBody] string name)
//{
// //这种写法是不行的,FromBody只能指定一个参数
// var context = HttpContext.Request;
// return Ok(new { id = id, name = name });
//}
}
public class dto
{
public string id { get; set; }
public string name { get; set; }
}
3. 通过配置SuppressInferBindingSourcesForParameters禁用默认推理规则
services.AddControllers(options => {
//其他配置
}).ConfigureApiBehaviorOptions(options =>
{
//禁用当[FromForm]属性批注时,推理multipart/form-data请求内容类型
//options.SuppressConsumesConstraintForFormFileParameters = true;
//禁用api的推理规则,这样就支持post方式直接括号接受参数和model参数方式
options.SuppressInferBindingSourcesForParameters = true;
});
4. 禁用推理规则后,WebAPI默认从form中取参,此时接参方式
/// <summary>
/// 禁用参数推理规则时
/// </summary>
[ApiController]
[Route("api/[controller]/[action]")]
public class Test1Controller : ControllerBase
{
[HttpPost]
public IActionResult AddFormPara1(string id)
{
//application/x-www-form-urlencoded
//禁用推理规则后,application/x-www-form-urlencoded对于简单类型就不需要显示指定参数来源FromForm
//但对于application/json的还是接不到
var context = HttpContext.Request;
return Ok(new { id = id });
}
[HttpPost]
public IActionResult AddFormPara(string id,string name)
{
//application/x-www-form-urlencoded
//禁用推理规则后,application/x-www-form-urlencoded对于简单类型就不需要显示指定参数来源FromForm
//但对于application/json的还是接不到
var context = HttpContext.Request;
return Ok(new { id = id, name = name });
}
[HttpPost]
public IActionResult AddJsonPara(dto1 dto)
{
//application/x-www-form-urlencoded
//禁用推理规则后,依然可以用实体类来接收json格式数据,但前提是application/x-www-form-urlencoded
var context = HttpContext.Request;
return Ok(new { id = dto.id, name = dto.name });
}
[HttpPost]
public IActionResult AddListJsonPara([FromBody]List<dto1> dto)
{
//禁用推理规则后,对于json格式数据集合参数,需指定FromBody
var context = HttpContext.Request;
return Ok(dto);
}
}
public class dto1
{
public string id { get; set; }
public string name { get; set; }
}
5. 总结
对于.NET Core WebAPI的默认推理规则,最好还是要开启。针对简单类型,需要显示指定 [FromBody] 或者 [FromForm]。对于json格式参数和数据集合参数按默认规则接收即可。