views:

97

answers:

2

I'm looking to make a really simple route in my ASP.NET MVC 2.0 website. I've been googling for help but all the examples I can find are for really complex routing.

Basically I want all the pages in my Home Controller to resolve after the domain as opposed to /Home/

For example I want http://www.MyWebsite.com/Home/LandingPage/

To become http://www.MyWebsite.com/LandingPage/

But only for the Home controller, I want the rest of my controllers to function as normal.

I thought about creating a controller for each and just using an index, but we need lots of landing pages for our marketing like this and it would quickly make the site loaded with controllers for a single page each, which is less than ideal.

A: 

I think you are missing the default route.

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

So, when you type www.mywebsite.com, the controller, action, and id parameters would have the following values:

controller : Home    
action: Index    
id : ""
CodeToGlory
+1  A: 

One way to do this would be to have a separate route for each landing page. Another way would be to have a single route with a constraint that matches each landing page (and nothing else).

 routes.MapRoute(
        "LandingPage1"
        "landingpage1/{id}",
        new { controller = "home", action = "landingpage", id = UrlParameter.Optional } );

 routes.MapRoute(
        "LandingPage2"
        "landingpage2/{id}",
        new { controller = "home", action = "landingpage2", id = UrlParameter.Optional } );

Note that you could probably do this with a bit of reflection as well (untested).

 foreach (var method on typeof(HomeController).GetMethods())
 {
      if (method.ReturnType.IsInstanceOf(typeof(ActionResult)))
      {
          routes.MapRoute(
               method.Name,
               method.Name + "/{id}",
               new { controller = "home", action = method.Name, id = UrlParameter.Optional } );
      }
 }

The RouteConstraint solution would be similar except that you'd have a single route with a custom constraint that evaluated whether the appropriate route value matched one of the methods on the HomeController and, if so, replaced the controller and action with "home" and the matched value.

routes.MapRoute(
     "LandingPage",
     "{action}/{id}",
     new { controller = "home", action = "index", id = UrlParameter.Optional },
     new LandingPageRouteConstraint()
);


public LandingPageRouteContstraint : IRouteConstraint
{
    public bool Match
        (
            HttpContextBase httpContext, 
            Route route, 
            string parameterName, 
            RouteValueDictionary values, 
            RouteDirection routeDirection
        )
    {
        // simplistic, you'd also likely need to check that it has the correct return
        // type, ...
        return typeof(HomeController).GetMethod( values.Values["action"] ) != null;
    }
}

Note that the route per page mechanism, even if you use reflection, is done only once. From then on you do a simple look up each time. The RouteConstraint mechanism will use reflection each time to see if the route matches (unless it caches the results, which I don't think it does).

tvanfosson
Perfect, that helps tons. Thanks!
Duk