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

2

6

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?

Baboon answered 8/4, 2019 at 8:35 Comment(0)
M
9

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)
    {
        ...
    }
}
Mosa answered 8/4, 2019 at 13:0 Comment(3)
Ah that explains it! What would happen if you had two parameters of the same type, e.g. Get(int companyId, int personId) and you wanted to use just the personId, would you need to call Customer/Get?personId=1234? I.e. is the routing using the parameter's type or the parameter name to do the matching?Baboon
Yes. It will bind via the name.Mosa
I don't understand why they did not make it possible to overload methods for different parameters... Make an If/else-if/else-if/..../else is very unpleasant when you deal with QueryString parameters that can be combined together or not...Heinrike
G
0

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)
    {
    }
Glaucoma answered 2/4, 2022 at 23:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.