diff --git a/samples/RoutingSample.Web/RoutingSample.Web.kproj b/samples/RoutingSample.Web/RoutingSample.Web.kproj
index 7d2e68bedd..733bc0bafd 100644
--- a/samples/RoutingSample.Web/RoutingSample.Web.kproj
+++ b/samples/RoutingSample.Web/RoutingSample.Web.kproj
@@ -20,6 +20,9 @@
28778
+
+ 22209
+
diff --git a/src/Microsoft.AspNet.Routing/Constraints/RequiredRouteConstraint.cs b/src/Microsoft.AspNet.Routing/Constraints/RequiredRouteConstraint.cs
new file mode 100644
index 0000000000..899470b4dc
--- /dev/null
+++ b/src/Microsoft.AspNet.Routing/Constraints/RequiredRouteConstraint.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
+{
+ ///
+ /// Constraints a route parameter that must have a value.
+ ///
+ ///
+ /// This constraint is primarily used to enforce that a non-parameter value is present during
+ /// URL generation.
+ ///
+ public class RequiredRouteConstraint : 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)
+ {
+ // In routing the empty string is equivalent to null, which is equivalent to an unset value.
+ var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
+ return !string.IsNullOrEmpty(valueString);
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Routing/Microsoft.AspNet.Routing.kproj b/src/Microsoft.AspNet.Routing/Microsoft.AspNet.Routing.kproj
index 8b6727ba9a..6b0e870438 100644
--- a/src/Microsoft.AspNet.Routing/Microsoft.AspNet.Routing.kproj
+++ b/src/Microsoft.AspNet.Routing/Microsoft.AspNet.Routing.kproj
@@ -41,6 +41,7 @@
+
diff --git a/test/Microsoft.AspNet.Routing.Tests/Constraints/RequiredRouteConstraintTests.cs b/test/Microsoft.AspNet.Routing.Tests/Constraints/RequiredRouteConstraintTests.cs
new file mode 100644
index 0000000000..818cb2f564
--- /dev/null
+++ b/test/Microsoft.AspNet.Routing.Tests/Constraints/RequiredRouteConstraintTests.cs
@@ -0,0 +1,98 @@
+// 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 Microsoft.AspNet.Http;
+using Microsoft.AspNet.Routing.Constraints;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNet.Routing.Tests
+{
+ public class RequiredRouteConstraintTests
+ {
+ [Theory]
+ [InlineData(RouteDirection.IncomingRequest)]
+ [InlineData(RouteDirection.UrlGeneration)]
+ public void RequiredRouteConstraint_NoValue(RouteDirection direction)
+ {
+ // Arrange
+ var constraint = new RequiredRouteConstraint();
+
+ // Act
+ var result = constraint.Match(
+ Mock.Of(),
+ Mock.Of(),
+ "area",
+ new RouteValueDictionary(new { controller = "Home", action = "Index" }),
+ direction);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Theory]
+ [InlineData(RouteDirection.IncomingRequest)]
+ [InlineData(RouteDirection.UrlGeneration)]
+ public void RequiredRouteConstraint_Null(RouteDirection direction)
+ {
+ // Arrange
+ var constraint = new RequiredRouteConstraint();
+
+ // Act
+ var result = constraint.Match(
+ Mock.Of(),
+ Mock.Of(),
+ "area",
+ new RouteValueDictionary(new { controller = "Home", action = "Index", area = (string)null }),
+ direction);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Theory]
+ [InlineData(RouteDirection.IncomingRequest)]
+ [InlineData(RouteDirection.UrlGeneration)]
+ public void RequiredRouteConstraint_EmptyString(RouteDirection direction)
+ {
+ // Arrange
+ var constraint = new RequiredRouteConstraint();
+
+ // Act
+ var result = constraint.Match(
+ Mock.Of(),
+ Mock.Of(),
+ "area",
+ new RouteValueDictionary(new { controller = "Home", action = "Index", area = string.Empty}),
+ direction);
+
+ // Assert
+ Assert.False(result);
+ }
+
+ [Theory]
+ [InlineData(RouteDirection.IncomingRequest)]
+ [InlineData(RouteDirection.UrlGeneration)]
+ public void RequiredRouteConstraint_WithValue(RouteDirection direction)
+ {
+ // Arrange
+ var constraint = new RequiredRouteConstraint();
+
+ // Act
+ var result = constraint.Match(
+ Mock.Of(),
+ Mock.Of(),
+ "area",
+ new RouteValueDictionary(new { controller = "Home", action = "Index", area = "Store" }),
+ direction);
+
+ // Assert
+ Assert.True(result);
+ }
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Routing.Tests/Microsoft.AspNet.Routing.Tests.kproj b/test/Microsoft.AspNet.Routing.Tests/Microsoft.AspNet.Routing.Tests.kproj
index 04c3acab62..2d852ad36b 100644
--- a/test/Microsoft.AspNet.Routing.Tests/Microsoft.AspNet.Routing.Tests.kproj
+++ b/test/Microsoft.AspNet.Routing.Tests/Microsoft.AspNet.Routing.Tests.kproj
@@ -40,6 +40,7 @@
+