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