I’ve recently been looking in to building a directory type application with Asp.Net MVC
One of the requirements would be to have SEO friendly URLs such as:
http://www.mysite.com/restaurants/Camberley—Surrey
/restaurants being the “Category”
/Camberley—Surrey being the “Location”
So, I created a ‘CategoryController’ like this
public class CategoryController : Controller { public ActionResult Index(string category, string location) { //do stuff return View(); } }
But how do I map my routes?
What you can use, is RouteConstraints
Simply map your route as usual, but add an instance of our custom RouteConstraint
routes.MapRoute( name: "CategoryRoute", url: "{category}/{location}", defaults: new { controller = "Category", action = "Index", location = UrlParameter.Optional }, constraints: new { category = new CategoryRouteConstraint() } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
With our CategoryRouteConstraint as follows:
public class CategoryRouteConstraint : IRouteConstraint { public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { //these would usually come from a database, or cache. var categories = new[] { "restaurants", "cafes", "bistros" }; if (values[parameterName] == null) return false; //get the category passed in to the route var category = values[parameterName].ToString(); //now we check our categories, and see if it exists return categories.Any(x => x == category.ToLower()); // url such as /restaurants/Camberley--Surrey will match // url such as /pubs/Camberley--Surrey will not } }
Of course, our collection of ‘categories’ would come from some kind of store – a database, cache, etc…
Now, if we run the app and visit /restaurants/Camberley–Surrey, our route resolves as we expect.
Demo: On github
Leave a Reply