views:

449

answers:

3

I am on the way to build an ASP.NET MVC application with the latest beta release and I wonder if it is possible to change the default project Layout of

/Views/Home/Index.aspx /Views/Home/About.aspx

to

/Blog/Views/Home/Index.aspx /Blog/Views/Home/About.aspx

/Forum/Views/Home/Index.aspx /Forum/Views/Home/About.aspx

The goal is to get some separation between "applications" within one single Web project, something like Thomas Owens asked already here: http://stackoverflow.com/questions/178398/under-an-mvc-framework-which-directory-structure-would-be-expected-by-other-dev

Of course this should include the Controllers as well, not only the Views.

+1  A: 

Yes, it should be possible to do this. I can think of one way; there may be others.

The first step is to modify the default route to include your application name:

routes.MapRoute("Default",
                "{applicationName}/{controller}/{action}/{id})",
                null, null);

I'm presuming that you're going to group the two "applications" into different namespaces within a single assembly. So you might have two namespaces like:

  • MyApp.Blog.Controllers
  • MyApp.Forum.Controllers

Next, you need to change the controller factory so that it instantiates the right controller. You can do this by subtyping the DefaultControllerFactory and overriding the GetControllerType method:

    protected override System.Type GetControllerType(string controllerName)
    {
        string applicationName;
        if (RequestContext != null && 
           RequestContext.RouteData.Values.TryGetValue(
           "applicationName", out applicationName)) {
           // return controller type using app name to 
           // look up namespace and controllerName argument
           return ...
        }

        // if no match, maybe it's a different controller/route
        return base.GetControllerType(controllerName);
    }

Finally, you need to tell MVC to use your ControllerFactory. In Global.asax.cs:

    private void Application_Start(object sender, EventArgs e)
    {
        RegisterRoutes(RouteTable.Routes);
        ControllerBuilder.Current.SetControllerFactory(
            MyApp.MyControllerFactory());
    }

Locating views can be handled similarly. In this case, you subtype WebFormViewEngine.

Craig Stuntz
This technique solved a related issue for me, trying to implement hierarchical controllers.
Giraffe
A: 

This is not a new concept. It is called "areas" in Monorail. There has been a lot of buzz about this topic lately on the ATL.NET forum and elsewhere. Steve Sanderson has come up with a way to do this but apparently it leaves some issues. In reseponse, apparently the MVC team is going to take a "deep look" at it for a future release.

Tim Scott
Thanks a lot, Tim, and Craig too. It seems to be the best way to wait for the final release and not playing around with this hacks, which alle seem to be not perfect at all today. Maybe I should use WebForms again until ASP.NET MVC is 100% ready :-(.
+1  A: 

I just wrote a blog post that describes one approach to grouping controllers that's similar to "areas" in monorail. It doesn't address nested areas yet though.

http://haacked.com/archive/2008/11/04/areas-in-aspnetmvc.aspx

Haacked