Is it possible to have multiple GETs that differ only in the parameters in ASP.NET Core?

I want to create a truly RESTful web service, so I don't want to use the RPC style, so at the moment this is:

[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)
{
}

And I believe this will work in the ASP.NET Web API. But I get an exception:

AmbiguousActionException: several actions are performed. The following actions were consistent with route data and met all restrictions:

TermsController.GetByParticipant (MemberTerms.Api)

TermsController.GetByProgram (MemberTerms.Api)

None of the attributes help:

  • [HttpGet]
  • [ActionName]
  • [FromQuery]
+4
source share
2 answers

, . 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) {
        //...
    }
}
+5

, 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

Source: https://habr.com/ru/post/1686585/


All Articles