views:

161

answers:

1

So my application is growing and I'd like to split out my View-based controllers from my JSON-based controllers. Basically, I have a bunch of controllers that all they do is return JSON results for AJAX calls.

What I would like to do would be to set up the routes (and the folder structure under my Controllers folder, for that matter) such that my JSON controllers live under /RPC/ and my regular controllers live under / -- i.e. my JavaScript would call /RPC/SomeController/SomeAction and my regular pages would live under /SomeOtherController/SomeOtherAction.

So what I did was I set up my Controllers folder as such:

  • Controllers (folder)
    • RPC (folder)
      • JsonController1
      • JsonController2
    • ViewController1
    • ViewContoller2
    • ViewController3

I wasn't able to just go to /RPC/JsonController1/Index and have that work so then I set up my routes as follows:

protected void Application_Start()
{
 AreaRegistration.RegisterAllAreas();

 RegisterRoutes(RouteTable.Routes);

 // Register new annotations.
 DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(UniqueUsernameAttribute), typeof(UniqueUsernameValidator));
}

public static void RegisterRoutes(RouteCollection routes)
{
 // Add the combres routes, too
 routes.AddCombresRoute("Combres");
 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 routes.MapRoute("RPC", 
  "RPC/{controller}/{action}/{id}", 
  new { controller = "None", action = "Index", id = UrlParameter.Optional },
  new[] { "Backplane.Web.Controllers.RPC" }
 );

 routes.MapRoute(
  "Default", // Route name
  "{controller}/{action}/{id}", // URL with parameters
  new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
  new[] { "Backplane.Web.Controllers" }
 );
}

This works just great! My controllers are accessible under both /RPC/ and /! Unforunately I can validly access /RPC/ViewController1/and I can also validly access /JsonController1/.

It seems that I have a fundamental misunderstanding about routing and how it's related to the physical path on the file system. Will I need a custom route scheme here? I'd like to keep all of this in the same project as I'd like to keep all the controllers in the same DLL.

A: 

The routing is not related to the physical path on the file system (either on the build machine or on the server). The routing is performed at run-time, at which point there are no artifacts that would suggest the MVC routing handler where on the file system particular class was located. As such, the routing is dependent only on the order of the routes in the routing table (which depends on the order of them in the Global.asax.cs) and how the URL path parts map onto the routes and the controller classes names and actions.

The easiest solution to make your scenario work is to remove the Default rule and list explicit rules for any controller under the root.

Another approach would be to move all your RPC controllers into a separate area (Areas/RPC/Controllers) in your solution. The way the areas work is that any /rpc/* path is mapped to the RPC area. There are certain caveats with that approach as well, but in general it should work, as the area routes are registered after the main routes and the MVC routing does an attempt to avoid using controllers that are part of an area with URLs that don't map to that area.

Franci Penov