我想构建真正的RESTful Web服务,所以不想利用RPC风格,所以目前有这个:
[HttpGet]
[ActionName(nameof(GetByParticipant))]
public async Task<IActionResult> GetByParticipant([FromQuery]string participantId, [FromQuery]string participantType, [FromQuery]string programName)
{
}
[HttpGet]
[ActionName(nameof(GetByProgram))]
public async Task<IActionResult> GetByProgram([FromQuery]string programName)
{
}
我认为这可以在ASP.NET Web API中使用。但是我得到了一个例外:
AmbiguousActionException:匹配多个动作。以下操作匹配路由数据并满足所有约束:
TermsController.GetByParticipant(ParticipantTerms.Api)
TermsController.GetByProgram(ParticipantTerms.Api)
这两个属性实际上都没有帮助:
[HttpGet]
[ActionName]
[FromQuery]
答案 0 :(得分:8)
您可以使用IActionConstraint执行此操作。
以下是一个例子:
public class ExactQueryParamAttribute : Attribute, IActionConstraint
{
private readonly string[] keys;
public ExactQueryParamAttribute(params string[] keys)
{
this.keys = keys;
}
public int Order => 0;
public bool Accept(ActionConstraintContext context)
{
var query = context.RouteContext.HttpContext.Request.Query;
return query.Count == keys.Length && keys.All(key => query.ContainsKey(key));
}
}
[HttpGet]
[ActionName(nameof(GetByParticipant))]
[ExactQueryParam("participantId", "participantType", "programName")]
public async Task<IActionResult> GetByParticipant([FromQuery]string participantId, [FromQuery]string participantType, [FromQuery]string programName)
{
}
[HttpGet]
[ActionName(nameof(GetByProgram))]
[ExactQueryParam("programName")]
public async Task<IActionResult> GetByProgram([FromQuery]string programName)
{
}
答案 1 :(得分:6)
从查询中使用时,您需要唯一地区分操作&#39;路线否则你会得到模棱两可的动作例外。原因api/action?participantId=1&participantType=2
与api/action?programName=x
建议:
public class ParticipantQuery {
public string participantId { get; set; }
public string participantType { get; set; }
public string programName { get; set; }
}
[Route("api/[controller]")]
public class TermsController : Controller {
[HttpGet("participants")] //GET api/terms/participants?participantId=123&....
[ActionName(nameof(GetByParticipant))]
public async Task<IActionResult> GetByParticipant([FromQuery]ParticipantQuery model) {
//...
}
[HttpGet("programs/{programName}")]//GET api/terms/programs/name
[ActionName(nameof(GetByProgram))]
public async Task<IActionResult> GetByProgram(string programName) {
//...
}
}
或者您可以使用一个封装可用参数的操作,并根据提供的成员分支结果
public class GetTermsQuery {
public string participantId { get; set; }
public string participantType { get; set; }
public string programName { get; set; }
}
[Route("api/[controller]")]
public class TermsController : Controller {
[HttpGet] //GET api/terms?participantId=123&....
public async Task<IActionResult> Get([FromQuery]GetTermsQuery model) {
//...
}
}
答案 2 :(得分:2)
我已经花了整整一天的时间尝试这样做,而且安德鲁·拉德福德(Andrew Radford)的解决方案非常完美!
[HttpGet]
[ExactQueryParam("active")]
public IEnumerable<UserSelectAllSprocResult.DataRow> GetAll(
[FromQuery] bool active)
{
return ...
}
[HttpGet]
[ExactQueryParam("active", "companyId")]
public IEnumerable<UserSelectAllByCompanySprocResult.DataRow> GetByCompanyId(
[FromQuery] bool active, [FromQuery] int companyId)
{
return ...;
}