diff --git a/samples/RoutingSample.Web/Startup.cs b/samples/RoutingSample.Web/Startup.cs
index 6c4891ebbb..9e04b33f59 100644
--- a/samples/RoutingSample.Web/Startup.cs
+++ b/samples/RoutingSample.Web/Startup.cs
@@ -45,11 +45,11 @@ namespace RoutingSample.Web
routeBuilder.MapRoute("regexStringRoute",
"api/rconstraint/{controller}",
new { foo = "Bar" },
- new { controller = new RegexConstraint("^(my.*)$") });
+ new { controller = new RegexRouteConstraint("^(my.*)$") });
routeBuilder.MapRoute("regexRoute",
"api/r2constraint/{controller}",
new { foo = "Bar2" },
- new { controller = new RegexConstraint(new Regex("^(my.*)$")) });
+ new { controller = new RegexRouteConstraint(new Regex("^(my.*)$")) });
routeBuilder.MapRoute("parameterConstraintRoute",
"api/{controller}/{*extra}",
diff --git a/src/Microsoft.AspNet.Routing/Constraints/AlphaRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/AlphaRouteConstraint.cs
new file mode 100644
index 0000000000..c6b7672e0b
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/AlphaRouteConstraint.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to contain only lowercase or uppercase letters A through Z in the English alphabet.
+ ///
+ public class AlphaRouteConstraint : RegexRouteConstraint
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public AlphaRouteConstraint() : base(@"^[a-z]*$")
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/BoolRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/BoolRouteConstraint.cs
new file mode 100644
index 0000000000..cc8eb6c967
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/BoolRouteConstraint.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to represent only Boolean values.
+ ///
+ public class BoolRouteConstraint : IRouteConstraint
+ {
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ if (value is bool)
+ {
+ return true;
+ }
+
+ bool result;
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ return Boolean.TryParse(valueString, out result);
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/DateTimeRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/DateTimeRouteConstraint.cs
new file mode 100644
index 0000000000..93b6130dc5
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/DateTimeRouteConstraint.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to represent only values.
+ /// Supports date time formats represented by CultureInfo.DateTimeFormat for the CultureInfo.InvariantCulture.
+ ///
+ public class DateTimeRouteConstraint : IRouteConstraint
+ {
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ if (value is DateTime)
+ {
+ return true;
+ }
+
+ DateTime result;
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ return DateTime.TryParse(valueString, CultureInfo.InvariantCulture, DateTimeStyles.None, out result);
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/DecimalRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/DecimalRouteConstraint.cs
new file mode 100644
index 0000000000..45382ed9dc
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/DecimalRouteConstraint.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to represent only decimal values.
+ ///
+ public class DecimalRouteConstraint : IRouteConstraint
+ {
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ if (value is decimal)
+ {
+ return true;
+ }
+
+ decimal result;
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ return Decimal.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out result);
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/DoubleRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/DoubleRouteConstraint.cs
new file mode 100644
index 0000000000..90e53666ea
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/DoubleRouteConstraint.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to represent only 64-bit floating-point values.
+ ///
+ public class DoubleRouteConstraint : IRouteConstraint
+ {
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ if (value is double)
+ {
+ return true;
+ }
+
+ double result;
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ return Double.TryParse(valueString,
+ NumberStyles.Float | NumberStyles.AllowThousands,
+ CultureInfo.InvariantCulture,
+ out result);
+ }
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/FloatRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/FloatRouteConstraint.cs
new file mode 100644
index 0000000000..276995c752
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/FloatRouteConstraint.cs
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to represent only 32-bit floating-point values.
+ ///
+ public class FloatRouteConstraint : IRouteConstraint
+ {
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ if (value is float)
+ {
+ return true;
+ }
+
+ float result;
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ return Single.TryParse(valueString,
+ NumberStyles.Float | NumberStyles.AllowThousands,
+ CultureInfo.InvariantCulture,
+ out result);
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/GuidRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/GuidRouteConstraint.cs
new file mode 100644
index 0000000000..d6bb7e6c8d
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/GuidRouteConstraint.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to represent only values.
+ /// Matches values specified in any of the five formats "N", "D", "B", "P", or "X",
+ /// supported by Guid.ToString(string) and Guid.ToString(String, IFormatProvider) methods.
+ ///
+ public class GuidRouteConstraint : IRouteConstraint
+ {
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ if (value is Guid)
+ {
+ return true;
+ }
+
+ Guid result;
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ return Guid.TryParse(valueString, out result);
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/LengthRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/LengthRouteConstraint.cs
new file mode 100644
index 0000000000..1d41153d0b
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/LengthRouteConstraint.cs
@@ -0,0 +1,91 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to be a string of a given length or within a given range of lengths.
+ ///
+ public class LengthRouteConstraint : IRouteConstraint
+ {
+ ///
+ /// Initializes a new instance of the class that constrains
+ /// a route parameter to be a string of a given length.
+ ///
+ /// The length of the route parameter.
+ public LengthRouteConstraint(int length)
+ {
+ if (length < 0)
+ {
+ var errorMessage = Resources.FormatArgumentMustBeGreaterThanOrEqualTo(0);
+ throw new ArgumentOutOfRangeException("length", length, errorMessage);
+ }
+
+ MinLength = MaxLength = length;
+ }
+
+ ///
+ /// Initializes a new instance of the class that constrains
+ /// a route parameter to be a string of a given length.
+ ///
+ /// The minimum length allowed for the route parameter.
+ /// The maximum length allowed for the route parameter.
+ public LengthRouteConstraint(int minLength, int maxLength)
+ {
+ if (minLength < 0)
+ {
+ var errorMessage = Resources.FormatArgumentMustBeGreaterThanOrEqualTo(0);
+ throw new ArgumentOutOfRangeException("minLength", minLength, errorMessage);
+ }
+
+ if (maxLength < 0)
+ {
+ var errorMessage = Resources.FormatArgumentMustBeGreaterThanOrEqualTo(0);
+ throw new ArgumentOutOfRangeException("maxLength", maxLength, errorMessage);
+ }
+
+ if (minLength > maxLength)
+ {
+ var errorMessage =
+ Resources.FormatRangeConstraint_MinShouldBeLessThanOrEqualToMax("minLength", "maxLength");
+ throw new ArgumentOutOfRangeException("minLength", minLength, errorMessage);
+ }
+
+ MinLength = minLength;
+ MaxLength = maxLength;
+ }
+
+ ///
+ /// Gets the minimum length allowed for the route parameter.
+ ///
+ public int MinLength { get; private set; }
+
+ ///
+ /// Gets the maximum length allowed for the route parameter.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ var length = valueString.Length;
+ return length >= MinLength && length <= MaxLength;
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/LongRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/LongRouteConstraint.cs
new file mode 100644
index 0000000000..7a357921df
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/LongRouteConstraint.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to represent only 64-bit integer values.
+ ///
+ public class LongRouteConstraint : IRouteConstraint
+ {
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ if (value is long)
+ {
+ return true;
+ }
+
+ long result;
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ return Int64.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out result);
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/MaxLengthRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/MaxLengthRouteConstraint.cs
new file mode 100644
index 0000000000..e0e9dd81f5
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/MaxLengthRouteConstraint.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to be a string with a maximum length.
+ ///
+ public class MaxLengthRouteConstraint : IRouteConstraint
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The maximum length allowed for the route parameter.
+ public MaxLengthRouteConstraint(int maxLength)
+ {
+ if (maxLength < 0)
+ {
+ var errorMessage = Resources.FormatArgumentMustBeGreaterThanOrEqualTo(0);
+ throw new ArgumentOutOfRangeException("maxLength", maxLength, errorMessage);
+ }
+
+ MaxLength = maxLength;
+ }
+
+ ///
+ /// Gets the maximum length allowed for the route parameter.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ return valueString.Length <= MaxLength;
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/MaxRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/MaxRouteConstraint.cs
new file mode 100644
index 0000000000..0100a81808
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/MaxRouteConstraint.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to be an integer with a maximum value.
+ ///
+ public class MaxRouteConstraint : IRouteConstraint
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The maximum value allowed for the route parameter.
+ public MaxRouteConstraint(long max)
+ {
+ Max = max;
+ }
+
+ ///
+ /// Gets the maximum allowed value of the route parameter.
+ ///
+ public long Max { get; private set; }
+
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ long longValue;
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ if (Int64.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out longValue))
+ {
+ return longValue <= Max;
+ }
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/MinLengthRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/MinLengthRouteConstraint.cs
new file mode 100644
index 0000000000..b729af9f05
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/MinLengthRouteConstraint.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to be a string with a minimum length.
+ ///
+ public class MinLengthRouteConstraint : IRouteConstraint
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The minimum length allowed for the route parameter.
+ public MinLengthRouteConstraint(int minLength)
+ {
+ if (minLength < 0)
+ {
+ var errorMessage = Resources.FormatArgumentMustBeGreaterThanOrEqualTo(0);
+ throw new ArgumentOutOfRangeException("minLength", minLength, errorMessage);
+ }
+
+ MinLength = minLength;
+ }
+
+ ///
+ /// Gets the minimum length allowed for the route parameter.
+ ///
+ public int MinLength { get; private set; }
+
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ return valueString.Length >= MinLength;
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/MinRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/MinRouteConstraint.cs
new file mode 100644
index 0000000000..cc387cafb1
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/MinRouteConstraint.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constrains a route parameter to be a long with a minimum value.
+ ///
+ public class MinRouteConstraint : IRouteConstraint
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The minimum value allowed for the route parameter.
+ public MinRouteConstraint(long min)
+ {
+ Min = min;
+ }
+
+ ///
+ /// Gets the minimum allowed value of the route parameter.
+ ///
+ public long Min { get; private set; }
+
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ long longValue;
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ if (Int64.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out longValue))
+ {
+ return longValue >= Min;
+ }
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/RangeRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/RangeRouteConstraint.cs
new file mode 100644
index 0000000000..e5cda4c8d0
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/RangeRouteConstraint.cs
@@ -0,0 +1,65 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Microsoft.AspNet.Http;
+
+namespace Microsoft.AspNet.Routing.Constraints
+{
+ ///
+ /// Constraints a route parameter to be an integer within a given range of values.
+ ///
+ public class RangeRouteConstraint : IRouteConstraint
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The minimum value.
+ /// The maximum value.
+ /// The minimum value should be less than or equal to the maximum value.
+ public RangeRouteConstraint(long min, long max)
+ {
+ if (min > max)
+ {
+ var errorMessage = Resources.FormatRangeConstraint_MinShouldBeLessThanOrEqualToMax("min", "max");
+ throw new ArgumentOutOfRangeException("min", min, errorMessage);
+ }
+
+ Min = min;
+ Max = max;
+ }
+
+ ///
+ /// Gets the minimum allowed value of the route parameter.
+ ///
+ public long Min { get; private set; }
+
+ ///
+ /// Gets the maximum allowed value of the route parameter.
+ ///
+ public long Max { get; private set; }
+
+ ///
+ public bool Match([NotNull] HttpContext httpContext,
+ [NotNull] IRouter route,
+ [NotNull] string routeKey,
+ [NotNull] IDictionary values,
+ RouteDirection routeDirection)
+ {
+ object value;
+ if (values.TryGetValue(routeKey, out value) && value != null)
+ {
+ long longValue;
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ if (Int64.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out longValue))
+ {
+ return longValue >= Min && longValue <= Max;
+ }
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Constraints/RegexConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/RegexRouteConstraint.cs
similarity index 87%
rename from src/Microsoft.AspNet.Routing/Constraints/RegexConstraint.cs
rename to src/Microsoft.AspNet.Routing/Constraints/RegexRouteConstraint.cs
index a49c66524b..49ec279dea 100644
--- a/src/Microsoft.AspNet.Routing/Constraints/RegexConstraint.cs
+++ b/src/Microsoft.AspNet.Routing/Constraints/RegexRouteConstraint.cs
@@ -9,14 +9,14 @@ using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Routing.Constraints
{
- public class RegexConstraint : IRouteConstraint
+ public class RegexRouteConstraint : IRouteConstraint
{
- public RegexConstraint([NotNull] Regex regex)
+ public RegexRouteConstraint([NotNull] Regex regex)
{
Constraint = regex;
}
- public RegexConstraint([NotNull] string regexPattern)
+ public RegexRouteConstraint([NotNull] string regexPattern)
{
Constraint = new Regex(regexPattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
}
diff --git a/src/Microsoft.AspNet.Routing/DefaultInlineConstraintResolver.cs b/src/Microsoft.AspNet.Routing/DefaultInlineConstraintResolver.cs
index c0bd82ab83..c57e0746d5 100644
--- a/src/Microsoft.AspNet.Routing/DefaultInlineConstraintResolver.cs
+++ b/src/Microsoft.AspNet.Routing/DefaultInlineConstraintResolver.cs
@@ -102,7 +102,7 @@ namespace Microsoft.AspNet.Routing
{
throw new InvalidOperationException(
Resources.FormatDefaultInlineConstraintResolver_CouldNotFindCtor(
- constraintTypeInfo.Name, argumentString.Length));
+ constraintTypeInfo.Name, arguments.Length));
}
else if (constructorMatches == 1)
{
@@ -113,7 +113,7 @@ namespace Microsoft.AspNet.Routing
{
throw new InvalidOperationException(
Resources.FormatDefaultInlineConstraintResolver_AmbiguousCtors(
- constraintTypeInfo.Name, argumentString.Length));
+ constraintTypeInfo.Name, arguments.Length));
}
}
diff --git a/src/Microsoft.AspNet.Routing/InlineRouteParameterParser.cs b/src/Microsoft.AspNet.Routing/InlineRouteParameterParser.cs
index a3726c8e36..a76c808a88 100644
--- a/src/Microsoft.AspNet.Routing/InlineRouteParameterParser.cs
+++ b/src/Microsoft.AspNet.Routing/InlineRouteParameterParser.cs
@@ -78,18 +78,18 @@ namespace Microsoft.AspNet.Routing
}
private static IRouteConstraint GetInlineConstraint(Group constraintGroup,
- IInlineConstraintResolver constraintResolver)
+ IInlineConstraintResolver _constraintResolver)
{
var parameterConstraints = new List();
foreach (Capture constraintCapture in constraintGroup.Captures)
{
var inlineConstraint = constraintCapture.Value;
- var constraint = constraintResolver.ResolveConstraint(inlineConstraint);
+ var constraint = _constraintResolver.ResolveConstraint(inlineConstraint);
if (constraint == null)
{
throw new InvalidOperationException(
Resources.FormatInlineRouteParser_CouldNotResolveConstraint(
- constraintResolver.GetType().Name, inlineConstraint));
+ _constraintResolver.GetType().Name, inlineConstraint));
}
parameterConstraints.Add(constraint);
diff --git a/src/Microsoft.AspNet.Routing/Microsoft.AspNet.Routing.kproj b/src/Microsoft.AspNet.Routing/Microsoft.AspNet.Routing.kproj
index bddc4bd9d9..386d4eb8cb 100644
--- a/src/Microsoft.AspNet.Routing/Microsoft.AspNet.Routing.kproj
+++ b/src/Microsoft.AspNet.Routing/Microsoft.AspNet.Routing.kproj
@@ -25,8 +25,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -46,9 +60,9 @@
-
+
diff --git a/src/Microsoft.AspNet.Routing/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Routing/Properties/Resources.Designer.cs
index d3acb37cd9..10d5e4bcaa 100644
--- a/src/Microsoft.AspNet.Routing/Properties/Resources.Designer.cs
+++ b/src/Microsoft.AspNet.Routing/Properties/Resources.Designer.cs
@@ -10,6 +10,38 @@ namespace Microsoft.AspNet.Routing
private static readonly ResourceManager _resourceManager
= new ResourceManager("Microsoft.AspNet.Routing.Resources", typeof(Resources).GetTypeInfo().Assembly);
+ ///
+ /// Value must be greater than or equal to {0}.
+ ///
+ internal static string ArgumentMustBeGreaterThanOrEqualTo
+ {
+ get { return GetString("ArgumentMustBeGreaterThanOrEqualTo"); }
+ }
+
+ ///
+ /// Value must be greater than or equal to {0}.
+ ///
+ internal static string FormatArgumentMustBeGreaterThanOrEqualTo(object p0)
+ {
+ return string.Format(CultureInfo.CurrentCulture, GetString("ArgumentMustBeGreaterThanOrEqualTo"), p0);
+ }
+
+ ///
+ /// The value for argument '{0}' should be less than or equal to the value for the argument '{1}'.
+ ///
+ internal static string RangeConstraint_MinShouldBeLessThanOrEqualToMax
+ {
+ get { return GetString("RangeConstraint_MinShouldBeLessThanOrEqualToMax"); }
+ }
+
+ ///
+ /// The value for argument '{0}' should be less than or equal to the value for the argument '{1}'.
+ ///
+ internal static string FormatRangeConstraint_MinShouldBeLessThanOrEqualToMax(object p0, object p1)
+ {
+ return string.Format(CultureInfo.CurrentCulture, GetString("RangeConstraint_MinShouldBeLessThanOrEqualToMax"), p0, p1);
+ }
+
///
/// The '{0}' property of '{1}' must not be null.
///
diff --git a/src/Microsoft.AspNet.Routing/Resources.resx b/src/Microsoft.AspNet.Routing/Resources.resx
index cea33cad4e..364a133d65 100644
--- a/src/Microsoft.AspNet.Routing/Resources.resx
+++ b/src/Microsoft.AspNet.Routing/Resources.resx
@@ -117,6 +117,12 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ Value must be greater than or equal to {0}.
+
+
+ The value for argument '{0}' should be less than or equal to the value for the argument '{1}'.
+
The '{0}' property of '{1}' must not be null.
diff --git a/src/Microsoft.AspNet.Routing/RouteConstraintBuilder.cs b/src/Microsoft.AspNet.Routing/RouteConstraintBuilder.cs
index 97e89da806..fb0db9834b 100644
--- a/src/Microsoft.AspNet.Routing/RouteConstraintBuilder.cs
+++ b/src/Microsoft.AspNet.Routing/RouteConstraintBuilder.cs
@@ -58,7 +58,7 @@ namespace Microsoft.AspNet.Routing
var constraintsRegEx = "^(" + regexPattern + ")$";
- constraint = new RegexConstraint(constraintsRegEx);
+ constraint = new RegexRouteConstraint(constraintsRegEx);
}
constraints.Add(kvp.Key, constraint);
diff --git a/src/Microsoft.AspNet.Routing/RouteOptions.cs b/src/Microsoft.AspNet.Routing/RouteOptions.cs
index 2086e32d24..227f4d74aa 100644
--- a/src/Microsoft.AspNet.Routing/RouteOptions.cs
+++ b/src/Microsoft.AspNet.Routing/RouteOptions.cs
@@ -36,6 +36,26 @@ namespace Microsoft.AspNet.Routing
{
// Type-specific constraints
{ "int", typeof(IntRouteConstraint) },
+ { "bool", typeof(BoolRouteConstraint) },
+ { "datetime", typeof(DateTimeRouteConstraint) },
+ { "decimal", typeof(DecimalRouteConstraint) },
+ { "double", typeof(DoubleRouteConstraint) },
+ { "float", typeof(FloatRouteConstraint) },
+ { "guid", typeof(GuidRouteConstraint) },
+ { "long", typeof(LongRouteConstraint) },
+
+ // Length constraints
+ { "minlength", typeof(MinLengthRouteConstraint) },
+ { "maxlength", typeof(MaxLengthRouteConstraint) },
+ { "length", typeof(LengthRouteConstraint) },
+
+ // Min/Max value constraints
+ { "min", typeof(MinRouteConstraint) },
+ { "max", typeof(MaxRouteConstraint) },
+ { "range", typeof(RangeRouteConstraint) },
+
+ // Regex-based constraints
+ { "alpha", typeof(AlphaRouteConstraint) },
};
}
}
diff --git a/test/Microsoft.AspNet.Routing.Tests/Constraints/AlphaRouteConstraintTests.cs b/test/Microsoft.AspNet.Routing.Tests/Constraints/AlphaRouteConstraintTests.cs
new file mode 100644
index 0000000000..d10772fc1c
--- /dev/null
+++ b/test/Microsoft.AspNet.Routing.Tests/Constraints/AlphaRouteConstraintTests.cs
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+#if NET45
+
+using Microsoft.AspNet.Routing.Constraints;
+using Xunit;
+
+namespace Microsoft.AspNet.Routing.Tests
+{
+ public class AlphaRouteConstraintTests
+ {
+ [Theory]
+ [InlineData("alpha", true)]
+ [InlineData("a1pha", false)]
+ [InlineData("ALPHA", true)]
+ [InlineData("A1PHA", false)]
+ [InlineData("alPHA", true)]
+ [InlineData("A1pHA", false)]
+ [InlineData("AlpHA╥", false)]
+ [InlineData("", true)]
+ public void AlphaRouteConstraintTest(string parameterValue, bool expected)
+ {
+ // Arrange
+ var constraint = new AlphaRouteConstraint();
+
+ // Act
+ var actual = ConstraintsTestHelper.TestConstraint(constraint, parameterValue);
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Routing.Tests/Constraints/BoolRouteConstraintTests.cs b/test/Microsoft.AspNet.Routing.Tests/Constraints/BoolRouteConstraintTests.cs
new file mode 100644
index 0000000000..d4212fa2c6
--- /dev/null
+++ b/test/Microsoft.AspNet.Routing.Tests/Constraints/BoolRouteConstraintTests.cs
@@ -0,0 +1,44 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+#if NET45
+
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using Microsoft.AspNet.Http;
+using Microsoft.AspNet.Routing.Constraints;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNet.Routing.Tests
+{
+ public class BoolRouteConstraintTests
+ {
+ [Theory]
+ [InlineData("true", true)]
+ [InlineData("TruE", true)]
+ [InlineData("false", true)]
+ [InlineData("FalSe", true)]
+ [InlineData(" FalSe", true)]
+ [InlineData("True ", true)]
+ [InlineData(" False ", true)]
+ [InlineData(true, true)]
+ [InlineData(false, true)]
+ [InlineData(1, false)]
+ [InlineData("not-parseable-as-bool", false)]
+ public void BoolRouteConstraint(object parameterValue, bool expected)
+ {
+ // Arrange
+ var constraint = new BoolRouteConstraint();
+
+ // Act
+ var actual = ConstraintsTestHelper.TestConstraint(constraint, parameterValue);
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Routing.Tests/RouteConstraintsTests.cs b/test/Microsoft.AspNet.Routing.Tests/Constraints/CompositeRouteConstraintTests.cs
similarity index 52%
rename from test/Microsoft.AspNet.Routing.Tests/RouteConstraintsTests.cs
rename to test/Microsoft.AspNet.Routing.Tests/Constraints/CompositeRouteConstraintTests.cs
index 3f1fa3f2ec..26300a1b28 100644
--- a/test/Microsoft.AspNet.Routing.Tests/RouteConstraintsTests.cs
+++ b/test/Microsoft.AspNet.Routing.Tests/Constraints/CompositeRouteConstraintTests.cs
@@ -7,38 +7,19 @@ using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Microsoft.AspNet.Http;
-using Microsoft.AspNet.Routing.Constraints;
using Moq;
using Xunit;
namespace Microsoft.AspNet.Routing.Tests
{
- public class RouteConstraintsTests
+ public class CompositeRouteConstraintTests
{
- [Theory]
- [InlineData(42, true)]
- [InlineData("42", true)]
- [InlineData(3.14, false)]
- [InlineData("43.567", false)]
- [InlineData("42a", false)]
- public void IntRouteConstraint_Match_AppliesConstraint(object parameterValue, bool expected)
- {
- // Arrange
- var constraint = new IntRouteConstraint();
-
- // Act
- var actual = TestValue(constraint, parameterValue);
-
- // Assert
- Assert.Equal(expected, actual);
- }
-
[Theory]
[InlineData(true, true, true)]
[InlineData(true, false, false)]
[InlineData(false, true, false)]
[InlineData(false, false, false)]
- public void CompoundRouteConstraint_Match_CallsMatchOnInnerConstraints(bool inner1Result,
+ public void CompositeRouteConstraint_Match_CallsMatchOnInnerConstraints(bool inner1Result,
bool inner2Result,
bool expected)
{
@@ -48,7 +29,7 @@ namespace Microsoft.AspNet.Routing.Tests
// Act
var constraint = new CompositeRouteConstraint(new[] { inner1.Object, inner2.Object });
- var actual = TestValue(constraint, null);
+ var actual = ConstraintsTestHelper.TestConstraint(constraint, null);
// Assert
Assert.Equal(expected, actual);
@@ -69,28 +50,6 @@ namespace Microsoft.AspNet.Routing.Tests
.Verifiable();
return mock;
}
-
- private static void AssertMatchWasCalled(Mock mock, Times times)
- {
- mock.Verify(ConstraintMatchMethodExpression, times);
- }
-
- private static bool TestValue(IRouteConstraint constraint, object value, Action routeConfig = null)
- {
- var context = new Mock();
-
- IRouter route = new RouteCollection();
-
- if (routeConfig != null)
- {
- routeConfig(route);
- }
-
- var parameterName = "fake";
- var values = new Dictionary() { { parameterName, value } };
- var routeDirection = RouteDirection.IncomingRequest;
- return constraint.Match(context.Object, route, parameterName, values, routeDirection);
- }
}
}
diff --git a/test/Microsoft.AspNet.Routing.Tests/Constraints/ConstraintsTestHelper.cs b/test/Microsoft.AspNet.Routing.Tests/Constraints/ConstraintsTestHelper.cs
new file mode 100644
index 0000000000..e59bf2b070
--- /dev/null
+++ b/test/Microsoft.AspNet.Routing.Tests/Constraints/ConstraintsTestHelper.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+#if NET45
+
+using System;
+using System.Collections.Generic;
+using Microsoft.AspNet.Http;
+using Moq;
+
+namespace Microsoft.AspNet.Routing.Tests
+{
+ public class ConstraintsTestHelper
+ {
+ public static bool TestConstraint(IRouteConstraint constraint, object value, Action routeConfig = null)
+ {
+ var context = new Mock();
+
+ var route = new RouteCollection();
+
+ if (routeConfig != null)
+ {
+ routeConfig(route);
+ }
+
+ var parameterName = "fake";
+ var values = new Dictionary() { { parameterName, value } };
+ var routeDirection = RouteDirection.IncomingRequest;
+ return constraint.Match(context.Object, route, parameterName, values, routeDirection);
+ }
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Routing.Tests/Constraints/DateTimeRouteConstraintTests.cs b/test/Microsoft.AspNet.Routing.Tests/Constraints/DateTimeRouteConstraintTests.cs
new file mode 100644
index 0000000000..8fda375f82
--- /dev/null
+++ b/test/Microsoft.AspNet.Routing.Tests/Constraints/DateTimeRouteConstraintTests.cs
@@ -0,0 +1,58 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+#if NET45
+
+using System;
+using System.Collections.Generic;
+using Microsoft.AspNet.Routing.Constraints;
+using Xunit;
+
+namespace Microsoft.AspNet.Routing.Tests
+{
+ public class DateTimeRouteConstraintTests
+ {
+ public static IEnumerable