Asp.net core Routing with multiple optional parameters calling different action

Movva picture Movva · Jan 30, 2019 · Viewed 7.6k times · Source

In Asp.net WebApi2

when api/values/9b858599-7639-45da-acd6-a1323fb019b5 is called get Action is invoked.

Action with optional parameters.

When api/values/9b858599-7639-45da-acd6-a1323fb019b5?maxRecords=100 or api/values/?maxRecords=100 GetProducts Action is invoked.

In Asp.net Core

But in asp.net core when api/values/9b858599-7639-45da-acd6-a1323fb019b5 is called GetProducts Action is getting invoked. I wanted to call Get action without changing existing url's.

How to fix this issue in Asp.net core 2.0

Contoller

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    //https://localhost:44323/api/values/9b858599-7639-45da-acd6-a1323fb019b5
    [HttpGet("{productId:Guid}", Order = 1)]
    public ActionResult<string> Get(Guid productId)
    {
        return "value1";
    }


    //https://localhost:44323/api/values/9b858599-7639-45da-acd6-a1323fb019b5?maxRecords=100
    //https://localhost:44323/api/values/?maxRecords=100
    [HttpGet("{startRecordId:Guid?}")]
    public ActionResult<IEnumerable<string>> GetProducts(Guid? startRecordId, int maxRecords, DateTimeOffset? minimumChangeDate = null)
    {
        return new string[] { "value1", "value2" };

    }

}

Startup.cs

app.UseMvc(routes =>
        {
            routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
            routes.MapRoute("DefaultApi", "api/{controller}/{id?}");
        });

Answer

Gregory A. Owen picture Gregory A. Owen · Feb 14, 2019

While not ideal, and this is a temporary shoehorn, till you can update the client calls. You could try this, if you can assume that you must have a maxRecords QueryString. Since if it defaults to 0 it is useless, unless you have logic in place in the case that it is 0.

    //https://localhost:44323/api/values/9b858599-7639-45da-acd6-a1323fb019b5
    [HttpGet("{productId:Guid}", Order = 1)]
    public ActionResult<string> Get(Guid productId)
    {
        return "value1";
    }


    //https://localhost:44323/api/values/9b858599-7639-45da-acd6-a1323fb019b5?maxRecords=100
    //https://localhost:44323/api/values/?maxRecords=100
    [HttpGet("{startRecordId:Guid?}")]
    public ActionResult<IEnumerable<string>> GetProducts(Guid? startRecordId, [FromQuery] int maxRecords, [FromQuery] DateTimeOffset? minimumChangeDate = null)
    {
        if (!Request.GetDisplayUrl().Contains(nameof(maxRecords)) &&
            startRecordId.HasValue)
        {
            return Get(startRecordId.Value);
        }

        return new string[] { "value1", "value2" };

    }