Include and Exclude Constraints in ASP.NET MVC

Otherwise known as a white list or black list for route tokens, this simple IRouteConstraint is coming in handy and I thought i would share:

  1. public enum ListConstraintType {
  2.     Exclude,
  3.     Include
  4. }
  5.  
  6. public class ListConstraint : IRouteConstraint {
  7.     public ListConstraintType ListType { get; set; }
  8.     public IList<string> List { get; set; }
  9.  
  10.     public ListConstraint() : this(ListConstraintType.Include, new string[] { }) { }
  11.     public ListConstraint(params string[] list) : this(ListConstraintType.Include, list) { }
  12.     public ListConstraint(ListConstraintType listType, params string[] list) {
  13.         if (list == null) throw new ArgumentNullException("list");
  14.  
  15.         this.ListType = listType;
  16.         this.List = new List<string>(list);
  17.     }
  18.  
  19.     public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
  20.         if (string.IsNullOrEmpty(parameterName)) throw new ArgumentNullException("parameterName");
  21.         if (values == null) throw new ArgumentNullException("values");
  22.  
  23.         string value = values[parameterName.ToLower()] as string;
  24.         bool found = this.List.Any(s => s.Equals(value, StringComparison.OrdinalIgnoreCase));
  25.  
  26.         return this.ListType == ListConstraintType.Include ? found : !found;
  27.     }
  28. }

You can then use the ListConstraint like this:

  1. public static void RegisterRoutes(RouteCollection routes) {
  2.     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  3.     routes.IgnoreRoute("content/{*pathInfo}");
  4.     routes.IgnoreRoute("favicon.ico");
  5.  
  6.     routes.MapRoute(
  7.         "UserShortcuts",
  8.         "{action}/{id}",
  9.         new { controller = "user", id = "" },
  10.         new { action = new ListConstraint(ListConstraintType.Include, "signin", "signout") }
  11.     );
  12.  
  13.     routes.MapRoute(
  14.         "HomeShortcuts",
  15.         "{action}",
  16.         new { controller = "home" },
  17.         new { action = new ListConstraint("sitemap", "contact") } //default Include
  18.     );
  19.  
  20.     routes.MapRoute(
  21.         "Default",
  22.         "{controller}/{action}/{id}",
  23.         new { controller = "home", action = "index", id = "" },
  24.         new { id = new ListConstraint(ListConstraintType.Exclude, "123") }
  25.     );
  26. }
  27.  
  28. protected void Application_Start() {
  29.     RegisterRoutes(RouteTable.Routes);
  30. }

Which then allows only those included constraints to use the UserShortcuts route:

Or prevents the id of 123 from being used on the Default route:

 

Hope folks find this useful,

Jason Conway

No Comments