.net core Web API參數綁定規則


參數推理綁定

先從一個問題說起,微信小程序按照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] 不適用於具有特殊含義的任何復雜的內置類型,如 IFormCollection 和 CancellationToken。 綁定源推理代碼將忽略這些特殊類型。
[FromForm] 針對 IFormFile 和 IFormFileCollection 類型的操作參數進行推斷。 該特性不針對任何簡單類型或用戶定義類型進行推斷。
[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請求的一些細節做些說明。

文章中有錯誤的還請留言交流!!!

參考文章:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM