ASP.NET Core的Web API在调用过程中,经常涉及到Client端参数传递和Server端参数的接收的问题。其中参数主要包括URL参数,表单参数和路由参数等,如何处理好各种类型的参数传递,尤其是复杂类型参数的处理,是正确调用Web API的关键也是难点。
本文通过介绍FromQueryAttribute,FromRouteAttribute和FromBodyAttribute三个Attribute,来介绍如果在URL,表单和路由中传递对复杂的对象参数。
FromQueryAttribute: 通过调用WebAPI的URL参数绑定Action参数数据。
FromRouteAttribute: 通过调用WebAPI的URL的路由参数绑定Action参数数据。
FromBodyAttribute:通过Web请求中的body段数据绑定Action参数数据,一个Action方法,只能使用一次FromBodyAttribute属性。
我们通过一个获取足球明星信息的Web API来验证上述定义,包含单一的参数使用模式和混合参数的使用模式。
具体Player类代码如下,Web API完整代码请参考附录。
public class Player
{
public int Id { get; set; }
public string Name { get; set; }
public int Number { get; set; }
}
Server直接通过URL参数实例化对象。
[HttpGet]
[Route(nameof(playerGetByURL))]
public Player playerGetByURL([FromQuery]Player player)
{
return player;
}
Server直接通过路由参数实例化对象。
[HttpGet]
[Route(nameof(playerGetByRoute) + "/{id}/{name}/{number}")]
public Player playerGetByRoute([FromRoute] Player player)
{
return player;
}
Server直接通过请求的body段数据创建Player对象。
[HttpPost(nameof(playerGetByBody))]
public Player playerGetByBody([FromBody]Player player)
{
return player;
}
3. Body内容被Server直接实例化成了Player对象。
Server直接通过请求的body段数据和URL参数创建两个Player对象
[HttpPost(nameof(playerGetByBodyURL))]
public IEnumerable<Player> playerGetByBodyURL([FromBody]Player player1, [FromQuery]Player player2)
{
return new List<Player>(){
player1,player2
};
}
Server直接通过路由和URL参数创建两个Player对象
[HttpGet(nameof(playerGetByURLRoute) + "/{id}/{name}/{number}")]
public IEnumerable<Player> playerGetByURLRoute([FromQuery]Player player1, [FromRoute]Player player2)
{
return new List<Player>(){
player1,player2
};
}
Server直接通过Request的body段数据和路由参数创建两个Player对象
[HttpPost(nameof(playerGetByBodyRoute) + "/{id}/{name}/{number}")]
public IEnumerable<Player> playerGetByBodyRoute([FromBody]Player player1, [FromRoute]Player player2)
{
return new List<Player>(){
player1,player2
};
}
Server直接通过Web请求的body段数据,路由参数和URL参数创建三个Player对象
[HttpPost(nameof(playerGetByBodyRouteURL) + "/{id}/{name}/{number}")]
public IEnumerable<Player> playerGetByBodyRouteURL([FromBody]Player player1, [FromRoute]Player player2, [FromQuery]Player player3)
{
return new List<Player>(){
player1, player2, player3
};
}
FromQueryAttribute,FromRouteAttribute和FromBodyAttribute让Action中参数绑定的方式变得非常清晰。建议大家在开发中,采用这种显示指定的方式来处理代码,这样会让代码更便于管理。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using football.Models;
namespace football.Controllers
{
[ApiController]
[Route("[controller]")]
public class PlayersController : ControllerBase
{
private readonly ILogger<PlayersController> _logger;
public PlayersController(ILogger<PlayersController> logger)
{
_logger = logger;
}
[HttpGet]
[Route(nameof(playerGetByURL))]
public Player playerGetByURL([FromQuery]Player player)
{
return player;
}
[HttpGet]
[Route(nameof(playerGetByRoute) + "/{id}/{name}/{number}")]
public Player playerGetByRoute([FromRoute] Player player)
{
return player;
}
[HttpPost(nameof(playerGetByBody))]
public Player playerGetByBody([FromBody]Player player)
{
return player;
}
[HttpPost(nameof(playerGetByBodyURL))]
public IEnumerable<Player> playerGetByBodyURL([FromBody]Player player1, [FromQuery]Player player2)
{
return new List<Player>(){
player1,player2
};
}
[HttpPost(nameof(playerGetByBodyRoute) + "/{id}/{name}/{number}")]
public IEnumerable<Player> playerGetByBodyRoute([FromBody]Player player1, [FromRoute]Player player2)
{
return new List<Player>(){
player1,player2
};
}
[HttpGet(nameof(playerGetByURLRoute) + "/{id}/{name}/{number}")]
public IEnumerable<Player> playerGetByURLRoute([FromQuery]Player player1, [FromRoute]Player player2)
{
return new List<Player>(){
player1,player2
};
}
[HttpPost(nameof(playerGetByBodyRouteURL) + "/{id}/{name}/{number}")]
public IEnumerable<Player> playerGetByBodyRouteURL([FromBody]Player player1, [FromRoute]Player player2, [FromQuery]Player player3)
{
return new List<Player>(){
player1, player2, player3
};
}
}
}