Search code examples
c#asp.net-mvc-5asp.net-mvc-routingurl-routing

MVC5: route two different urls into one action method designating them by the input parameter


Let's assume I have a following action method:

[Route("option/{id:int}")] // routing is incomplete
public ActionResult GetOption(int id, bool advanced)
{
    ...
    return View();
}

This action should be associated with two different routes:

  • the one that fetches results in a simple form: .../option/{id},
  • and its advanced version: .../option/{id}/advanced.

It is important to represent these routes as two separate urls, and not the same URL with optional query string parameter. The only difference between these URLs is in the last term, which is basically some form of designation. What I need is a way to setup the routing rules to tell framework that it should call same method for both types of requests passing true as a second parameter in case of 'advanced' requests, or false otherwise. There are substantial reasons why I need to encapsulate both routes into one action method. So, no, I can't add second method to handle 'advanced' requests separately.

The question is: How to setup such routing?


Solution

  • If you are able to change the type of the second parameter

    [HttpGet]
    [Route("option/{id:int}")] // GET option/1
    [Route("option/{id:int}/{*advanced}")] // GET option/1/advanced
    public ActionResult GetOption(int id, string advanced) {
        bool isAdvanced = "advanced".Equals(advanced);
    
        //...
    
        return View();
    }
    

    And as much as you are apposed to having separate actions you can simpy have one call the other to avoid repeating code (DRY)

    // GET option/1
    [HttpGet]
    [Route("option/{id:int}")] 
    public ActionResult GetOption(int id, bool advanced = false) {
        //...    
        return View("Option");
    }
    
    // GET option/1/advanced
    [HttpGet]
    [Route("option/{id:int}/advanced")]
    public ActionResult GetAdvancedOption(int id) {
        return GetOption(id, true);
    }