.Net core Web API参数绑定规则

本文详细解析了WebAPI中GET和POST请求参数绑定的规则,包括默认的推理机制和不同参数类型如何被解析。在POST请求中,简单类型参数如果没有明确指定绑定源,会被默认视为从Query中获取,导致无法在请求体中接收到。理解这些规则对于正确地设计和调用WebAPI至关重要。
摘要由CSDN通过智能技术生成

参数推理绑定

先从一个问题说起,微信小程序按照WebAPI定义的参数传递,Get请求服务器端可以正常接收到参数,但是Post请求取不到。
Web API代码(.netcore 3.1)如下:

[HttpGet("Login")]
public LoginResult Login(string code)
{
  ...
}
[HttpPost("PostAvatar")]
public BaseResult<string> PostAvatar(int id,string imgUrl)
{
...
}

客户端代码(微信小程序js)如下:

wx.request({
  url: '/api/Login',
  data:{code:'xxx'},
  method:'GET',
  success:function(res){}
})
wx.request({
  url: '/api/PostAvatar',
  data: { id: 1,imgUrl:'xxx' },
  method: 'POST',
  success: function (res) { }
})

后来发现如果把参数放在一个实体里就可以接收到,像这样

[HttpPost("PostAvatar")]
public BaseResult<string> PostAvatar(Avatar model)
{
...
}
...
public class Avatar 
{
   public int Id { get; set; }
   public string imgUrl{ get; set; }
}

于是找到官方文档对于绑定源参数推理的解释:

WEB API存在以下绑定源特性:
[FromBody] 请求正文
[FromForm] 请求正文中的表单数据
[FromHeader] 请求标头
[FromQuery] 请求查询字符串参数
[FromRoute] 当前请求中的路由数据
[FromServices] 作为操作参数插入的请求服务

Web API 还有一套默认的推理规则,意思就是上面的这些特性可以加在参数的前面用来强制的指定这个参数是用那种方式获取,但是如果不显式的声明,它会按照这套规则默认匹配。规则如下:

绑定源推理规则的行为如下:
[FromBody] 针对复杂类型参数进行推断。 [FromBody] 不适用于具有特殊含义的任何复杂的内置类型,如 IFormCollectionCancellationToken。 绑定源推理代码将忽略这些特殊类型。
[FromForm] 针对 IFormFileIFormFileCollection 类型的操作参数进行推断。 该特性不针对任何简单类型或用户定义类型进行推断。
[FromRoute] 针对与路由模板中的参数相匹配的任何操作参数名称进行推断。 当多个路由与一个操作参数匹配时,任何路由值都视为 [FromRoute]。
[FromQuery] 针对任何其他操作参数进行推断。

默认按照从上到下的顺序去匹配,最后才是FromQuery,所以最开始的问题就解释通了,因为简单类型的参数如果不显式指定类型就是从Query里取,而我们的用的post请求方式,参数都在body里所以服务器接收不到。

简单类型、复杂类型混合

知道了上面的推理规则,所以下面的这个例子里,wechat参数因为是简单类型所以不会跟其他的参数在一起,必须放在URL里。

[HttpPost("PostAvatar")]
public BaseResult<string> PostAvatar(Avatar model,int wechat)
{
...
}
...
public class Avatar 
{
   public int id { get; set; }
   public string imgUrl{ get; set; }
}

js的请求必须是这样才行

wx.request({
  url: '/api/PostAvatar?wechat=1',//增加在这
  data:{
    id:1,
    imgUrl:'',
    //wechat:1 放在data里一样取不到
  },
  method:"POST",
  success:function(res){
  ...
  }
})

key问题

问题还没完,如果想把所有POST请求使用统一的格式,单个参数也想放在body里请求,是不是按照上面的绑定规则显式指定为FromBody就可以呢?

public IActionResult Post([FromBody] string name) { ... }

答案是:依然取不到,因为js发送的body是这样的

{"name":"xxxx"}

webapi期望的body里只有xxxx

总结

Web API 参数的绑定如果不是显式的指定会按照一定默认规则识别参数的来源,GET请求比较简单从QueryString中取值,POST请求会因为参数的类型有所不同。

[FromBody][FromForm]还是有些差别的,涉及到了ContentType后续可能还会针对HTTP请求的一些细节做些说明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值