1

I am using the standard MVC template in VS 2013.

With the default set up, http://website/ will be routed to website/Home/Index.

How do I route all "actions" directly under website root url, eg http://website/xxx, to show the same content as http://website/Home/xxx? For example, how do I make http://website/About to execute the About action in the Home controller? If possible, the solution shouldn't be a Http redirect to http://website/Home/About because I don't want to show the "ugly" Home/ in the url.

Thom Wiggers
  • 6,938
  • 1
  • 39
  • 65
Old Geezer
  • 14,854
  • 31
  • 111
  • 198

2 Answers2

2

I couldn't find an answer to this that covered all issues one would face with a public facing website without being a pain to upkeep while still maintaining flexibility.

I ended up coming up with the following. It allows for use of multiple controllers, doesn't require any upkeep, and makes all URLs lowercase.

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        //set up constraints automatically using reflection - shouldn't be an issue as it only runs on appstart
        var homeConstraints = @"^(?:" + string.Join("|", (typeof(Controllers.HomeController)).GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.DeclaredOnly).Select(x => (x.Name == "Index" ? "" : x.Name))) + @")$";

        //makes all urls lowercase, which is preferable for a public facing website
        routes.LowercaseUrls = true;

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

        //maps routes with a single action to only those methods specified within the home controller thanks to contraints
        routes.MapRoute(
            "HomeController",
            "{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new { action = homeConstraints }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}
Nick Kuznia
  • 1,698
  • 17
  • 27
1

you can try out like the following one

routes.MapRoute(
                name: "MyAppHome",
                url: "{action}/{wa}",
                defaults: new { controller = "Home", action = "Index", wa = UrlParameter.Optional, area = "Admin" },
                namespaces: new string[] { "MyApp.Controllers" }
            ).DataTokens = new RouteValueDictionary(new { area = "Admin" });

Here, you may notice that the Home controller is hardcoded and is no longer to be supplied in the request. you can also make use of the RouteDebugger to play with routes.

HTH

Saravanan
  • 7,637
  • 5
  • 41
  • 72
  • Looks like there is an error in your code. I changed url to "{action}/{wa}" and it gives what I want, ie website/About will output content of website/Home/About. I have always wondered how it knows that in url:{A}/{B}/{C} what A is and what B is. In url:"{action}/{wa}" why doesn't it think that `action` is the controller? – Old Geezer Mar 29 '15 at 16:58
  • It was posted by oversight. It is because we have a default value for the controller and the URL is in the pattern that accepts only action and paramters – Saravanan Mar 29 '15 at 17:03
  • Thanks. My last question was: given the url website/X, how does it know that X should be a controller or an action? Eg, website/About should it be mapped to /Home/About or should it be mapped to /About/Index? – Old Geezer Mar 30 '15 at 00:25
  • I have hit an unwanted side effect. By adding the above code before the default routes.MapRoute in the built-in file, I lost all other /Controller/Action urls. For example /Account/Login now gives a 404. Does it mean that I have to add a route for every controller I have? – Old Geezer Apr 01 '15 at 08:19
  • Did you have a route for controller/action. Else, you can switch to attribute routing, which you can control easily – Saravanan Apr 03 '15 at 02:47
  • Thanks. I have rephrased the question at http://stackoverflow.com/questions/29386170/how-to-make-one-controller-the-default-one-when-only-action-specified and learned much about routing. There is no magic to it. It's just simple pattern matching. – Old Geezer Apr 03 '15 at 08:17