diff --git a/src/Microsoft.AspNet.Routing/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Routing/Properties/Resources.Designer.cs
index 8cdac84..a37cb32 100644
--- a/src/Microsoft.AspNet.Routing/Properties/Resources.Designer.cs
+++ b/src/Microsoft.AspNet.Routing/Properties/Resources.Designer.cs
@@ -42,6 +42,14 @@ namespace Microsoft.AspNet.Routing
get { return GetString("TemplateRoute_CannotHaveOptionalParameterInMultiSegment"); }
}
+ ///
+ /// A catch-all parameter cannot be marked optional.
+ ///
+ internal static string TemplateRoute_CatchAllCannotBeOptional
+ {
+ get { return GetString("TemplateRoute_CatchAllCannotBeOptional"); }
+ }
+
///
/// A catch-all parameter can only appear as the last segment of the route template.
///
diff --git a/src/Microsoft.AspNet.Routing/Resources.resx b/src/Microsoft.AspNet.Routing/Resources.resx
index 35e3037..5fa3960 100644
--- a/src/Microsoft.AspNet.Routing/Resources.resx
+++ b/src/Microsoft.AspNet.Routing/Resources.resx
@@ -129,6 +129,9 @@
A path segment that contains more than one section, such as a literal section or a parameter, cannot contain an optional parameter.
+
+ A catch-all parameter cannot be marked optional.
+
A catch-all parameter can only appear as the last segment of the route template.
diff --git a/src/Microsoft.AspNet.Routing/Template/TemplateParser.cs b/src/Microsoft.AspNet.Routing/Template/TemplateParser.cs
index 3b87fae..3a74597 100644
--- a/src/Microsoft.AspNet.Routing/Template/TemplateParser.cs
+++ b/src/Microsoft.AspNet.Routing/Template/TemplateParser.cs
@@ -178,6 +178,12 @@ namespace Microsoft.AspNet.Routing.Template
var isCatchAll = rawName.StartsWith("*", StringComparison.Ordinal);
var isOptional = rawName.EndsWith("?", StringComparison.Ordinal);
+ if (isCatchAll && isOptional)
+ {
+ context.Error = Resources.TemplateRoute_CatchAllCannotBeOptional;
+ return false;
+ }
+
rawName = isCatchAll ? rawName.Substring(1) : rawName;
rawName = isOptional ? rawName.Substring(0, rawName.Length - 1) : rawName;
diff --git a/test/Microsoft.AspNet.Routing.Tests/Template/TemplateParserTests.cs b/test/Microsoft.AspNet.Routing.Tests/Template/TemplateParserTests.cs
index 1f3ca9d..9140836 100644
--- a/test/Microsoft.AspNet.Routing.Tests/Template/TemplateParserTests.cs
+++ b/test/Microsoft.AspNet.Routing.Tests/Template/TemplateParserTests.cs
@@ -1,8 +1,7 @@
-using System;
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Xunit;
using Xunit.Extensions;
@@ -384,6 +383,15 @@ namespace Microsoft.AspNet.Routing.Template.Tests
"A path segment that contains more than one section, such as a literal section or a parameter, cannot contain an optional parameter." + Environment.NewLine +
"Parameter name: routeTemplate");
}
+
+ [Fact]
+ public void InvalidTemplate_CatchAllMarkedOptional()
+ {
+ Assert.Throws(
+ () => TemplateParser.Parse("{a}/{*b?}"),
+ "A catch-all parameter cannot be marked optional." + Environment.NewLine +
+ "Parameter name: routeTemplate");
+ }
private class TemplateParsedRouteEqualityComparer : IEqualityComparer
{
diff --git a/test/Microsoft.AspNet.Routing.Tests/Template/TemplateRouteTests.cs b/test/Microsoft.AspNet.Routing.Tests/Template/TemplateRouteTests.cs
index 8d80336..a97f956 100644
--- a/test/Microsoft.AspNet.Routing.Tests/Template/TemplateRouteTests.cs
+++ b/test/Microsoft.AspNet.Routing.Tests/Template/TemplateRouteTests.cs
@@ -722,6 +722,8 @@ namespace Microsoft.AspNet.Routing.Template.Tests
// Assert
Assert.NotNull(match);
+ Assert.Equal(2, match.Values.Count);
+ Assert.Equal("Home", match.Values["controller"]);
Assert.Equal("Index", match.Values["action"]);
}
@@ -737,6 +739,8 @@ namespace Microsoft.AspNet.Routing.Template.Tests
// Assert
Assert.NotNull(match);
+ Assert.Equal(1, match.Values.Count);
+ Assert.Equal("Home", match.Values["controller"]);
Assert.False(match.Values.ContainsKey("action"));
}
@@ -752,6 +756,8 @@ namespace Microsoft.AspNet.Routing.Template.Tests
// Assert
Assert.NotNull(match);
+ Assert.Equal(2, match.Values.Count);
+ Assert.Equal("Home", match.Values["controller"]);
Assert.Equal("Index", match.Values["action"]);
Assert.False(match.Values.ContainsKey("id"));
}