Luis Luis - 3 months ago 11
C# Question

Distinguish between web api routes and mvc routes

I started developing an application supported by Web API 2, because I just wanted to retrieve data in a RESTful way.

Then I needed to add some HTML to the site in order to allow administrators manage the information provided, so I created some MVC 5 controller to return HTML. Now I want to distinguish between Web API routes and MVC routes, without affecting, if possible, Web API routes, which are in production.

Web API routes: My mistake here was removing the "api" prefix when I firstly developed this, which would have solved the collision now

public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{action}/{id}",
defaults:
new {
controller = "Parking",
action = "Get",
id = RouteParameter.Optional
}
);
}


MVC Routes: default routing. MVC Controller name is Administration, that is, MVC routes are intended for administration site only

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Parking", action = "Get", id = UrlParameter.Optional }
);
}


The problem is that MVC routes don't have the opportunity to match because WebAPI routes match first. It doesn't really matter how MVC routes need to be changed as long as they just work, since they are not in production yet; it's better for me to keep Web API routes as they are now.

I've tried:


  • Switching the order of registration of web api routes and mvc routes in Global.asax.cs

  • Using "web" as prefix for the MVC controllers, but the routing mechanism thinks "web" is a controller and it is not found (Web api routing wins again).

  • I couldn't come up with a proper constraint to avoid this collision.

  • Hardcode "Administration" replacing "{controller}" in the MVC route pattern.



Is there some trick here to resolve the collision?

Answer

Finally made it with the following constraint in WebApiConfig:

constraints: new { controller = @"(?!web).*" }

So, this is my WebApiConfig:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "{controller}/{action}/{id}",
                defaults:
                    new
                    {
                        controller = "Parking",
                        action = "Get",
                        id = RouteParameter.Optional
                    },
                constraints: new { controller = @"(?!web).*" }
            );
        }
    }

And my RouteConfig:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "web/{controller}/{action}/{id}",
        defaults: new { controller = "Parking", action = "Get", id = UrlParameter.Optional }
    );
}
Comments