tomRedox
tomRedox

Reputation: 30453

How to overload controller methods with same number of arguments in ASP.NET Core Web API?

I'm migrating a full .NET Framework Web API 2 REST project over to ASP.NET Core 2.2 and getting a bit lost in the routing.

In Web API 2 I was able to overload routes with the same number of parameters based on the parameter type, e.g. I could have Customer.Get(int ContactId) and Customer.Get(DateTime includeCustomersCreatedSince) and incoming requests would be routed accordingly.

I haven't been able to achieve the same thing in .NET Core, I either get a 405 error or a 404 and this error instead:

"{\"error\":\"The request matched multiple endpoints. Matches: \r\n\r\n[AssemblyName].Controllers.CustomerController.Get ([AssemblyName])\r\n[AssemblyName].Controllers.CustomerController.Get ([AssemblyName])\"}"

This was working code in my full .NET framework app Web API 2 app:

[RequireHttps]    
public class CustomerController : ApiController
{
    [HttpGet]
    [ResponseType(typeof(CustomerForWeb))]
    public async Task<IHttpActionResult> Get(int contactId)
    {
       // some code
    }

    [HttpGet]
    [ResponseType(typeof(List<CustomerForWeb>))]
    public async Task<IHttpActionResult> Get(DateTime includeCustomersCreatedSince)
    {
        // some other code
    }
}

And this is what I converted it to in Core 2.2:

[Produces("application/json")]
[RequireHttps]
[Route("api/[controller]")]
[ApiController]
public class CustomerController : Controller
{
    public async Task<ActionResult<CustomerForWeb>> Get([FromQuery] int contactId)
    {
        // some code
    }

    public async Task<ActionResult<List<CustomerForWeb>>> Get([FromQuery] DateTime includeCustomersCreatedSince)
    {
        // some code
    }
}

The code above works if I comment out one of Get methods, but fails as soon as I have two Get methods. I'd expected the FromQuery to use the parameter name in the request to steer the routing, but that doesn't seem to be the case?

Is it possible to overload a controller method like this where you have the same number of parameters and either route based on the parameter's type or the parameter's name?

Upvotes: 6

Views: 7744

Answers (2)

Zeko
Zeko

Reputation: 145

You can simply by using different route for each method e.g.

    [HttpPost("add")]
    public void add(string StringParam)
    {
    }

    [HttpPost("add-overload-1")]
    public void add(int IntParam)
    {
    }


    [HttpPost("add-overload-2")]
    public void add(bool BoolParam)
    {
    }

Upvotes: 0

Chris Pratt
Chris Pratt

Reputation: 239300

You cannot do action overloads. The way routing works in ASP.NET Core is different than how it did in ASP.NET Web Api. However, you can simply combine these actions and then branch inside, since all params are optional:

public async Task<ActionResult<CustomerForWeb>> Get(int contactId, DateTime includeCustomersCreatedSince)
{
    if (contactId != default)
    {
        ...
    }
    else if (includedCustomersCreatedSince != default)
    {
        ...
    }
}

Upvotes: 9

Related Questions