Reputation: 8950
This is my first post after being a long-time lurker - so please be gentle :-)
I have a website similar to twitter, in that people can sign up and choose a 'friendly url', so on my site they would have something like:
mydomain.com/benjones
I also have root level static pages such as:
mydomain.com/about
and of course my homepage:
mydomain.com/
I'm new to ASP.NET MVC 2 (in fact I just started today) and I've set up the following routes to try and achieve the above.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("content/{*pathInfo}");
routes.IgnoreRoute("images/{*pathInfo}");
routes.MapRoute("About", "about",
new { controller = "Common", action = "About" }
);
// User profile sits at root level so check for this before displaying the homepage
routes.MapRoute("UserProfile", "{url}",
new { controller = "User", action = "Profile", url = "" }
);
routes.MapRoute("Home", "",
new { controller = "Home", action = "Index", id = "" }
);
}
For the most part this works fine, however, my homepage is not being triggered! Essentially, when you browser to mydomain.com, it seems to trigger the User Profile route with an empty {url} parameter and so the homepage is never reached! Any ideas on how I can show the homepage?
Upvotes: 4
Views: 839
Reputation: 31
Know this question was asked a while back but I was just looking to do the same sort of thing and couldn't find any answer that quite solved it for me so I figured I'd add my 2 cents for others that may also look to do the same thing in future.
The problem with the proposed solution above (as mentioned in Astrofaes' comment) is that you would need to create static routes for every controller in your assembly. So in the end I ended up using a custom route constraint to check whether or not a controller exists in the executing assembly that could handle the request. If there is then return a false on the match so that the request will be handled by another route.
public class NotControllerConstraint : IRouteConstraint
{
private static readonly IEnumerable<Type> Controllers = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.BaseType == typeof(Controller));
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
return Controllers.Where(c => c.Name == values["id"] + "Controller").Count() == 0;
}
}
Routes can then be set up as follows:
routes.MapRoute("User", "{id}", new { controller = "User", action = "Index" }, new { notController = new NotControllerConstraint() });
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
Upvotes: 2
Reputation: 1233
I have a simlar setup as below:
routes.MapRoute(
"Common",
"common/{action}/{id}",
new { controller = "common", action = "Index", id = "" }
);
routes.MapRoute(
"Home",
"",
new { controller = "Home", action = "Index", id = "" }
);
routes.MapRoute(
"Dynamic",
"{id}",
new { controller = "dynamic", action = "Index", id = "" }
);
This allows me to be flexible and have the routes
mysite.com/
mysite.com/common/contact/ mysite.com/common/about/ mysite.com/common/{wildcard}/
mysite.com/{anything}
Upvotes: 0
Reputation: 75
I was looking to implement same style of url for my MVC 1.0 application.
I have implemented that with information from this post and blog post by Guy Burstein.
Thanks for sharing :)
Upvotes: 0
Reputation: 9771
The reason that swapping the routes works, is because the {url} route doesn't have a constraint on it against empty strings (which is what your last route is). As a result, it will match the empty string first as it's higher in the route table.
With that in mind, you can either add constraints or add your specifically named routes higher in the routes table, or use the default catch all routes that mvc gives you to start with.
If you want to know which routes are matching at any given moment, then you can use the Route Debugger from Phil Haack.
Upvotes: 1