xr280xr
xr280xr

Reputation: 13302

ASP.NET MVC Routing to sub directories without area

I've reorganized my project into a more logical hierarchy:

-Controllers  
  -Accounts  
    -CustomersController  
  -Setup  
    -SystemDefaultsController
    -SettingsController
  -HomeController

At the moment, I'm just trying to set up my URLs to match this structure. So valid example URLs would be:

localhost:1234/Home/Index
localhost:1234/Setup/SystemDefaults/Index
localhost:1234/Setup/Settings/Index
localhost:1234/CustomerAccounts/Index

So I added a route on top of the default route in RouteConfig.cs:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapMvcAttributeRoutes();

    //AreaRegistration.RegisterAllAreas();

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Setup",
        url: "Setup/{controller}/{action}/{id}",
        defaults: new { controller = "Setup", action = "Index", id = UrlParameter.Optional },
        namespaces: new[] { "MVCWeb.Controllers.Setup" }
    );

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        namespaces: new[] { "MVCWeb.Controllers" }
    );
}

This does make the above URLs work, but it has no constraints so these URLs work when I want them to be invalid:

localhost:1234/Setup/CustomerAccounts/Index localhost:1234/SystemDefaults/Index

Additionally, since the Setup route matches everything, if I do either of these:

@Html.ActionLink("Customer Accounts", "Index", "CustomerAccounts")
@Url.Action("Index", "CustomerAccounts")

It generates the URL as /Setup/CustomerAccounts/Index instead of /CustomerAccounts/Index.

Is there a way to do accomplish this without using an Area while still using {controller} in the route URL? Or would I have to add a route specifically for each controller under Setup?

Upvotes: 2

Views: 614

Answers (1)

thmshd
thmshd

Reputation: 5847

Have you ever evaluated Attribute Routing in MVC 5? It seems like you're starting a new project, so this could be a good new start. With the [RoutePrefix] attribute, you could probably enforce what you want to achieve easily:

[RoutePrefix("accounts")]
public class CustomersController : Controller
{
    // ...
}

We don't use Attribute Routing yet so I can't speak from own experience but it looks very flexible and promising.

UPDATE

  1. I created a GIST for you where I explain how you could validate your Attributes, not during compile time, but with Unit Tests. This is a simple code snipped designed for MS Test. The validation possibilities are very broad.

  2. Custom Logic we might add to a custom RoutePrefixAttribute? For example, the RoutePrefixAttribute allows a string as a parameter. You could rewrite it to allow only a specific Enum as parameter, which lists only possible values, and internally set the Prefix string.

Upvotes: 2

Related Questions