透過HttpClient呼叫RestAPI的Model Binding

當我們透過HttpClient要調用API時,Model Binding是一個重要的東西。要給API的參數可以來自URL網址參數,可以以來自網址路由,可以來自表單。

如果是POST的話,資料則是可以放在Body裡面。

這篇文章整理了一些比較常見的傳輸參數的作法。

Binding from [Route]

HttpClient Request
var clientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
_httpClient = new HttpClient(clientHandler);
var responseMsg = _httpClient.GetAsync("https://localhost/api/DesignAuditRise/GetDrawingData/TestUser/Type_1").Result;
var stream = responseMsg.Content.ReadAsStreamAsync().Result;

 

binding 個別參數

Controller:

[HttpGet("{userName}/{darType}")] //[HttpGet]換成[Route("{userName}/{darType}")]也是可以的
public async Task<IActionResult> GetDrawingData(string userName, string darType)
{...}

Binding from [Query]

HttpClient Request:

var clientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
_httpClient = new HttpClient(clientHandler);
var responseMsg = _httpClient.GetAsync("https://localhost/api/DesignAuditRise/GetDrawingData/data?param_1=TestUser&&param_2=Type_1").Result;
var stream = responseMsg.Content.ReadAsStreamAsync().Result;

 

binding 個別參數

Controller:

[HttpGet("data")]
public async Task<IActionResult> GetDrawingData(string param_1, string param_2)
{...}

 

binding 資料模型

Controller:

[HttpGet("data")]
public async Task<IActionResult> GetDrawingData([FromQuery]GetDrawingDataDto para)
{...}
  • 記得要加上 [FromQuery],不然會回應 415 Unsupported Media Type。但我記得以前在.NetFramework好像不用加這個,不知道是不是.Net才改成這樣子的。
  • URL的路由data,一定要跟[HttpGet("data")]一致,不然會無法binding成功。

Model:

[BindProperties]
public class GetDrawingDataDto
{
	[BindProperty(Name = "param_1", SupportsGet = true)]
	public string userName { get; set; }
	[BindProperty(Name = "param_2", SupportsGet = true)]
	public string darType { get; set; }
}
  • [BindProperties]. [BindProperty]不一定要加,但沒有加的話,URL的參數名稱就要跟Model的屬性名稱一樣。

 

雖然我們測試都是以[HttpGet]為主,但是換成[HttpPost]也是可以的,[HttpPost]也可以直接透過URL取得參數。 但是換成[HttpPost]也是可以的,[HttpPost]也可以直接透過URL取得參數。HttpClient的GetAsync也要記得改成PostAsync。

Binding from [Body]

HttpClient Request:

var clientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
_httpClient = new HttpClient(clientHandler);
var content = new StringContent(JsonConvert.SerializeObject(new { name = User.Identity.Name.Split('\\')[1], type = darType }), Encoding.UTF8, "application/json");
var responseMsg = _httpClient.PostAsync("https://localhost/api/DesignAuditRise/GetDrawingData").Result;
var stream = responseMsg.Content.ReadAsStreamAsync().Result;
  • [FromBody]預設會把參數轉為Json格式,Content-Type要記得用application/json,Content_Type用錯的話,會回應415

Controller:

[HttpPost]
public async Task<IActionResult> GetDrawingDataa([FromBody]GetDrawingDataDto data)
{...}

Model:

public class GetDrawingDataDto
{	
	public string userName { get; set; }
	public string darType { get; set; }
}
  • [FromBody]的參數名稱一定要跟資料模型的屬性名稱一樣,不用使用[BindProperty]設定識別名稱。

Binding from [Form]

to be continue…


總結:

  1. 要Binding資料模型:要記得在參數加上[FromQuery]. [FromBody]等Attribute。
  2. 不Binding資料模型:只要設定好[HttpGet]的識別項名稱
  3. [HttpPost]的資料是存放在Body之中,記得要設定正確的Content-Type(Json),[HttpGet]則不用設定Content-Type

 

Ref:
1.-NET 中如何選擇 WebClient,HttpClient,HttpWebRequest
2.ASP.NET Core Model Binding 死活綁不上 - 1
3.ASP.NET Core 中的資料繫結(MSDN)