Route Constraints

Route constraints let you restrict how the parameters in the route template are matched. The general syntax is {parameter:constraint}. For example:

  • // eg: /users/5
  • [Route(“users/{id:int}”]
  • public ActionResult GetUserById(int id) { … }
  •  
  • // eg: users/ken
  • [Route(“users/{name}”]
  • public ActionResult GetUserByName(string name) { … }

Here, the first route will only be selected if the “id” segment of the URI is an integer. Otherwise, the second route will be chosen.

The following table lists the constraints that are supported.

 

Constraint Description Example
alpha Matches uppercase or lowercase Latin alphabet characters (a-z, A-Z) {x:alpha}
bool Matches a Boolean value. {x:bool}
datetime Matches a DateTime value. {x:datetime}
decimal Matches a decimal value. {x:decimal}
double Matches a 64-bit floating-point value. {x:double}
float Matches a 32-bit floating-point value. {x:float}
guid Matches a GUID value. {x:guid}
int Matches a 32-bit integer value. {x:int}
length Matches a string with the specified length or within a specified range of lengths. {x:length(6)}
{x:length(1,20)}
long Matches a 64-bit integer value. {x:long}
max Matches an integer with a maximum value. {x:max(10)}
maxlength Matches a string with a maximum length. {x:maxlength(10)}
min Matches an integer with a minimum value. {x:min(10)}
minlength Matches a string with a minimum length. {x:minlength(10)}
range Matches an integer within a range of values. {x:range(10,50)}
regex Matches a regular expression. {x:regex(^\d{3}-\d{3}-\d{4}$)}

Notice that some of the constraints, such as “min”, take arguments in parentheses.

You can apply multiple constraints to a parameter, separated by a colon, for example:

  • // eg: /users/5
    // but not /users/10000000000 because it is larger than int.MaxValue,
    // and not /users/0 because of the min(1) constraint.
  • [Route(“users/{id:int:min(1)}”)]
  • public ActionResult GetUserById(int id) { … }

 

Specifying that a parameter is Optional (via the ‘?’ modifier) should be done after inline constraints:

 

  • // eg: /greetings/bye
    // and /greetings because of the Optional modifier,
    // but not /greetings/see-you-tomorrow because of the maxlength(3) constraint.
    [Route(“greetings/{message:maxlength(3)?}”)]
  • public ActionResult Greet(string message) { … }
Custom Route Constraints

You can create custom route constraints by implementing the IRouteConstraint interface. For example, the following constraint restricts a parameter to set of valid values:

  • public class ValuesConstraint : IRouteConstraint
  • {
  •     private readonly string[] validOptions;
  •     public ValuesConstraint(string options)
  •     {
  •         validOptions = options.Split(‘|’);
  •     }
  •  
  •     public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
  •     {
  •         object value;
  •         if (values.TryGetValue(parameterName, out value) && value != null)
  •         {
  •             return validOptions.Contains(value.ToString(), StringComparer.OrdinalIgnoreCase);
  •         }
  •         return false;
  •     }
  • }

The following code shows how to register the constraint:

  • public class RouteConfig
  • {
  •     public static void RegisterRoutes(RouteCollection routes)
  •     {
  •         routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);
  •  
  •         var constraintsResolver = new DefaultInlineConstraintResolver();
  •  
  •         constraintsResolver.ConstraintMap.Add(“values”, typeof(ValuesConstraint));
  •  
  •         routes.MapMvcAttributeRoutes(constraintsResolver);
  •     }
  • }

Now you can apply the constraint in your routes:

  • public class TemperatureController : Controller
  • {
  •     // eg: temp/celsius and /temp/fahrenheit but not /temp/kelvin
  •     [Route(“temp/{scale:values(celsius|fahrenheit)}”)]
  •     public ActionResult Show(string scale)
  •     {
  •         return Content(“scale is “ + scale);
  •     }
  • }
  •  

Custom Route Constraints