Using a default controller in ASP.Net MVC

One common question about ASP.Net MVC is how to make “default” controller.

Most websites will have a Home controller with actions like About, FAQ, Privacy, or similar pages.  Ordinarily, these actions can only be accessed through URLs like ~/Home/About.  Most people would prefer to put these URLs directly off the root: ~/About, etc.

Unfortunately, there is no obvious way to do that in ASP.Net MVC without making a separate route or controller for each action.

You cannot simply create a route matching "/{action}" and map it to the Home controller, since such a route would match any URL with exactly one term, including URLs meant for other controllers.  Since the routing engine is not aware of MVC actions, it doesn’t know that this route should only match actions that actually exist on the controller.

To make it work, we can add a custom route constraint that forces this route to only match URLs that correspond to actual methods on the controller.

To this end, I wrote an extension method that scans a controller for all action methods and adds a route that matches actions in that controller. The code is available at gist.github.com/1225676.  It can be used like this:

routes.MapDefaultController<Controllers.HomeController>();

This maps the route "/{action}/{id}" (with id optional) to all actions defined in HomeController.   Note that this code ignores custom ActionNameSelectorAttributes (The built-in [ActionName(…)] is supported).

For additional flexibility, you can also create custom routes that will only match actions in a specific controller.  This is useful if you have a single controller with a number of actions that has special route requirements that differ from the rest of your site.

For example:

routes.MapControllerActions<UsersController>(
    name: "User routes",
    url:  "{userName}/{action}"
    defaults: new { action = "Index" }
);

(Note that this example will also match URLs intended for other controllers with the same actions; plan your routes carefully)

8 comments:

Thanks a lot for this wonderful post, I am little bit new to this MVC and Routing thing.
I was confused that how MapDefaultController is available when I enter routes. I mean to say that in this line:
routes.MapDefaultController();
how come MapDefaultController becomes part of routes?

That's an extension method.

You need to include it in your project, from https://gist.github.com/1225676

And for anyone as noobish as I was. Remember to actually use the namespace in which you have included SLaks' genious extension. I.e. like this:

using SLaks.Web.Mvc;

I am wondering however... Did I do something wrong since this is not working with the @Html.ActionLink ? It keeps giving me an URL with the controller in it.

Html.ActionLink will use the first route it finds in the routing table that can handle the parameters you gave it.

You need to register this route before the default {controller}/{action}/{id}, or ActionLink() will still find the default first.

In MVC 4 Basic Project, there is an easy fix, and that is because the setup creates a RouteConfig.vb/cs in App_Start. The name of the default controller out of the box is "Home" (very obvious when you view the file), so if you want another controller to be the default, just change "Home" to "YourControllerName"

@Matt: That's not what I'm talking about.

That default route has been there since ASP.Net MVC 1.0.

However, that won't help you map URLs like /About to HomeController.About(). See my fourth paragraph.

if i am setting maproute as controller='account' and action='logon'.how to change maproute controller='home' and action='index' after login?
please help me.

Post a Comment