Search code examples
c#asp.net-mvcasp.net-mvc-5asp.net-mvc-routingoptional-parameters

MVC Routing many optional parameters


I'm working on a site that will have the ability to filter a list of items based on user selection, much like you can filter the results of an amazon search. I'm not sure how to build a route that can accept many various parameters, of which none are required.

ideally, the final result would look something like:

  1. mysite.com/dothings/filter1/sometext/filter5/sometext/filter11/sometext

or

  1. mysite.com/dothings/filter1:sometext/filter5:sometext/filter11:sometext

for both of these, I don't understand how to set up the routes to handle random filters / random ordering of filters.

Currently my code is just:

//the real code would have 10+ filters
[Route("filter1/{filter1}/filter2/{filter2}")]
public IActionResult DoThings(string filter1 = null, string filter2 = null)
{
    return Ok("Test");
}

but even with the optional parameter, if I leave out filter1 it doesn't hit my action at all.

Is there a common approach to this type of requirement?


Solution

  • The reason it does not hit your action when you leave a filter out, is because you have the filters as part of the route.

    If you have filter1 = null; filter2 = "foo" then this is the scenario:

    • Expect: ../filter1/{filter1}/filter2/{filter2}
    • Actual: ../filter1/filter2/foo

    Instead you should use query parameters. Then the query will look like this:

    mysite.com/dothings?filter1=sometext&filter5=sometext&filter11=sometext

    And the route will look like:

    [Route("DoThings")]
    public IActionResult DoThings(string filter1 = null, string filter2 = null)
    {
        return Ok("Test");
    }
    

    Also since you mentioned that this will have 10+ parameters I would suggest creating a class for the filters. For example:

    public class MyFilters 
    {
        public string filter1 { get; set; }
        public string filter2 { get; set; }
        ...
    }
    

    [Route("DoThings")]
    public IActionResult DoThings(MyFilters filters)
    {
        return Ok("Test");
    }
    

    Here are some related questions: