Search code examples
asp.net-mvcasp.net-mvc-5routesurl-routingasp.net-mvc-routing

Action Prefix to ASP.NET MVC Routing


I would like to set up a route that submits to a controller with a prefixed action.

For example, I have a ProvidersController for service providers, and I have a ProviderType model that I'd like to handle within the Providers controller (it's a lightweight object and I just assume not set up new controllers specifically for each of these little supporting objects, thus I want to group them into the Providers controller).

So, my ProvidersController has standard actions for managing providers:

public class ProvidersController : ControllerBase
{
    public ActionResult Index() { }
    public ActionResult Create() { }
    public ActionResult Edit(int id) { }
    // ect ect
}

I'd like to handle ProviderTypes in here as well:

public class ProvidersController : ControllerBase
{
    public ActionResult Index() { }
    public ActionResult Create() { }
    public ActionResult Edit(int id) { }
    // ect ect
    public ActionResult TypeIndex() { }
    public ActionResult TypeCreate() { }
    public ActionResult TypeEdit(int id) { }
    // ect ect
}

This is all fine, expect I want my routing to "look like" a Type is nested:

~/Providers/Create
~/Providers/Types/Create

Here's a route I had in mind:

routes.MapRoute(
    name: "ProviderTypes",
    url: "Providers/Types/{action}/{id}",
    defaults: new { controller = "Providers", action = "Index", id = UrlParameter.Optional }
);

But this would require I use a ~/Providers/Types/TypeCreate route, which I don't like.

Is there some way I can "intercept" this route and add a "Type" prefix to the action so it maps to the controller action correctly but provides a clean URL the way I'd like?

E.g., how would I get ~/Providers/Types/Create to map to ProvidersController.TypeCreate()?

(as a general note, I'm trying to avoid attribute routing as I like to have all my route definitions coming from one place instead of scattered throughout)


Solution

  • You could enable ASP.NET MVC Attribute Routing

    in RouteConfig.cs

    public static void RegisterRoutes(RouteCollection routes){
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
        //enabling attribute routing
        routes.MapMvcAttributeRoutes();
    
        //You can also combine attribute routing with convention-based routing.
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
    

    Then in your ProvidersController

    [RoutePrefix("Providers"]
    public class ProvidersController : ControllerBase {
        //eg: GET Providers
        [Route("")]
        public ActionResult Index() {...}
        //eg: GET Providers/Create
        [Route("Create")]
        public ActionResult Create() {...}
        //eg: GET Providers/Edit/5
        [Route("Edit/{id:int}")]
        public ActionResult Edit(int id) {...}
        // ...
    
        //eg: GET Providers/Types
        [Route("Types")]
        public ActionResult TypeIndex() {...}
        //eg: GET Providers/Types/Create
        [Route("Types/Create")]
        public ActionResult TypeCreate() {...}
        //eg: GET Providers/Types/Edit/5
        [Route("Types/Edit/{id:int}")]
        public ActionResult TypeEdit(int id) {...}
        // ...
    }