Tom
Tom

Reputation: 16276

MVC3 areas and routing structure

I am making Areas for User, Admin, Shop, Forum... etc

In each area, it has its own Controllers, Models, Views folders. At the root Models, root Controllers and root Views I have shared components in them.

Structure A:

Root/ -> Models/, Controllers/, Views/
Root/User/ -> Models/, Controllers/, Views/
Root/Admin/ -> Models/, Controllers/, Views/
Root/Shop/ -> Models/, Controllers/, Views/
Root/Forum/ -> Models/, Controllers/, Views/

I maybe wrong, but they really don't look DRY to me to repeat M V and C folders in each of the business logic groups. I was thinking a better structure would be using M V and C as the main folders and layout my business logic groups in them:

Structure B:

Root/Views/ -> User/, Admin/, Shop/, Forum/ ...etc
Root/Models/ -> User/, Admin/, Shop/, Forum/ ...etc
Root/Controllers/ -> User/, Admin/, Shop/, Forum/ ...etc

But if I do structure the folders this way, I lost the area (or from users point of view, the sub folder path) ability to divde logical functionalities of the website.

e.g.

with structure A, I can do:

www.mywebsite.com/Users(area)/Account(controller)/LogOn(action)
www.mywebsite.com/Admin(area)/Account(controller)/LogOn(action) 

Notice I can have same controller and action names with different areas.

With structure B, best I can do is:

www.mywebsite.com/AdminAccount(controller)/LogOn(action)
www.mywebsite.com/UserAccount(controller)/LogOn(action)

It can not achieve the single-word sub-folder result without area. If not only that, the controller names here can get longer and more messy very soon. Not to mention you have a large group of actions stacking in same controller.cs file.

So, anyway, my point is, if I find Structure B making more sense to me, how do I go about configuring routing to achieve that?

Upvotes: 0

Views: 221

Answers (1)

Kenneth Ito
Kenneth Ito

Reputation: 5261

So you want Structure B with url's corresponding to A?

You'll be giving up convention over configuration.

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

        routes.MapRoute(
            "UserAccount", // Route name
            "users/account/{action}/{id}", // URL with parameters
            new { controller = "UserAccount", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

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

Another option would be to write a custom route handler and introduce your own convention. Something like the following (new convention would be to concatenate Users and Account to get the UsersAccountController in www.mywebsite.com/Users/Account/LogOn). I did not test to see how this handles areas, but if you have issues let me know and I can take a look.

public class CustomConventionRouteHandler : MvcRouteHandler
{
    protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
    {
        string controller = requestContext.RouteData.Values["controller"].ToString();

        object controllerModifier;
        if (requestContext.RouteData.Values.TryGetValue("controllerModifier", out controllerModifier))
        {
            requestContext.RouteData.Values["controller"] = string.Concat(controllerModifier, controller);
        }

        return base.GetHttpHandler(requestContext);
    }
}

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

    routes.Add(
        new Route(
            "{controllerModifier}/{controller}/{action}",
            new RouteValueDictionary(new { controllerModifier = UrlParameter.Optional, controller = "Home", action = "Index" }),  //defaults
            new CustomConventionRouteHandler()));
}

Upvotes: 1

Related Questions