From 27bdec40a6a26c83e8219b94f99c692f15dd126f Mon Sep 17 00:00:00 2001 From: ianhong Date: Fri, 13 Mar 2015 14:51:59 -0700 Subject: [PATCH] React to #154 (Routing - adding data token to GetVirtualPath) --- .../MvcRouteHandler.cs | 2 +- .../Routing/AttributeRoute.cs | 2 +- .../Routing/InnerAttributeRoute.cs | 27 ++- src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs | 8 +- .../RemoteAttributeTest.cs | 2 +- .../Routing/InnerAttributeRouteTest.cs | 217 ++++++++++++------ .../UrlHelperTest.cs | 4 +- .../CustomRouteWebSite/LocalizedRoute.cs | 2 +- 8 files changed, 180 insertions(+), 84 deletions(-) diff --git a/src/Microsoft.AspNet.Mvc.Core/MvcRouteHandler.cs b/src/Microsoft.AspNet.Mvc.Core/MvcRouteHandler.cs index e6a944ae5c..b49149bf4b 100644 --- a/src/Microsoft.AspNet.Mvc.Core/MvcRouteHandler.cs +++ b/src/Microsoft.AspNet.Mvc.Core/MvcRouteHandler.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Mvc { private ILogger _logger; - public string GetVirtualPath([NotNull] VirtualPathContext context) + public VirtualPathData GetVirtualPath([NotNull] VirtualPathContext context) { // The contract of this method is to check that the values coming in from the route are valid; // that they match an existing action, setting IsBound = true if the values are OK. diff --git a/src/Microsoft.AspNet.Mvc.Core/Routing/AttributeRoute.cs b/src/Microsoft.AspNet.Mvc.Core/Routing/AttributeRoute.cs index d59ab43742..a08839b27a 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Routing/AttributeRoute.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Routing/AttributeRoute.cs @@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc.Routing } /// - public string GetVirtualPath(VirtualPathContext context) + public VirtualPathData GetVirtualPath(VirtualPathContext context) { var route = GetInnerRoute(); return route.GetVirtualPath(context); diff --git a/src/Microsoft.AspNet.Mvc.Core/Routing/InnerAttributeRoute.cs b/src/Microsoft.AspNet.Mvc.Core/Routing/InnerAttributeRoute.cs index eb9187be3b..f0b3212631 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Routing/InnerAttributeRoute.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Routing/InnerAttributeRoute.cs @@ -94,7 +94,7 @@ namespace Microsoft.AspNet.Mvc.Routing } /// - /// Gets the version of this route. This corresponds to the value of + /// Gets the version of this route. This corresponds to the value of /// when this route was created. /// public int Version { get; } @@ -142,7 +142,7 @@ namespace Microsoft.AspNet.Mvc.Routing } /// - public string GetVirtualPath([NotNull] VirtualPathContext context) + public VirtualPathData GetVirtualPath([NotNull] VirtualPathContext context) { // If it's a named route we will try to generate a link directly and // if we can't, we will not try to generate it using an unnamed route. @@ -157,7 +157,7 @@ namespace Microsoft.AspNet.Mvc.Routing foreach (var match in matches) { - var path = GenerateLink(context, match.Entry); + var path = GenerateVirtualPath(context, match.Entry); if (path != null) { context.IsBound = true; @@ -168,12 +168,12 @@ namespace Microsoft.AspNet.Mvc.Routing return null; } - private string GetVirtualPathForNamedRoute(VirtualPathContext context) + private VirtualPathData GetVirtualPathForNamedRoute(VirtualPathContext context) { AttributeRouteLinkGenerationEntry entry; if (_namedEntries.TryGetValue(context.RouteName, out entry)) { - var path = GenerateLink(context, entry); + var path = GenerateVirtualPath(context, entry); if (path != null) { context.IsBound = true; @@ -183,7 +183,7 @@ namespace Microsoft.AspNet.Mvc.Routing return null; } - private string GenerateLink(VirtualPathContext context, AttributeRouteLinkGenerationEntry entry) + private VirtualPathData GenerateVirtualPath(VirtualPathContext context, AttributeRouteLinkGenerationEntry entry) { // In attribute the context includes the values that are used to select this entry - typically // these will be the standard 'action', 'controller' and maybe 'area' tokens. However, we don't @@ -247,12 +247,12 @@ namespace Microsoft.AspNet.Mvc.Routing ProvidedValues = providedValues, }; - var path = _next.GetVirtualPath(childContext); - if (path != null) + var pathData = _next.GetVirtualPath(childContext); + if (pathData != null) { // If path is non-null then the target router short-circuited, we don't expect this // in typical MVC scenarios. - return path; + return pathData; } else if (!childContext.IsBound) { @@ -260,8 +260,13 @@ namespace Microsoft.AspNet.Mvc.Routing return null; } - path = entry.Binder.BindValues(bindingResult.AcceptedValues); - return path; + var path = entry.Binder.BindValues(bindingResult.AcceptedValues); + if (path == null) + { + return null; + } + + return new VirtualPathData(this, path); } private bool ContextHasSameValue(VirtualPathContext context, string key, object value) diff --git a/src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs b/src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs index a538b6d3bf..923cf32b75 100644 --- a/src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs +++ b/src/Microsoft.AspNet.Mvc.Core/UrlHelper.cs @@ -99,12 +99,16 @@ namespace Microsoft.AspNet.Mvc protected virtual string GeneratePathFromRoute(string routeName, IDictionary values) { var context = new VirtualPathContext(_httpContext, _ambientValues, values, routeName); - var path = _router.GetVirtualPath(context); - if (path == null) + var pathData = _router.GetVirtualPath(context); + if (pathData == null) { return null; } + // VirtualPathData.VirtualPath returns string.Empty for null. + Debug.Assert(pathData.VirtualPath != null); + + var path = pathData.VirtualPath; // See Routing Issue#31 if (path.Length > 0 && path[0] != '/') { diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/RemoteAttributeTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/RemoteAttributeTest.cs index c3233b7b82..bd7b4aae7e 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/RemoteAttributeTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/RemoteAttributeTest.cs @@ -529,7 +529,7 @@ namespace Microsoft.AspNet.Mvc handler .Setup(router => router.GetVirtualPath(It.IsAny())) .Callback(context => context.IsBound = isBound) - .Returns((string)null); + .Returns((VirtualPathData)null); builder.DefaultHandler = handler.Object; return builder; diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Routing/InnerAttributeRouteTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Routing/InnerAttributeRouteTest.cs index 78fc09468b..5dd4b4e7f8 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/Routing/InnerAttributeRouteTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/Routing/InnerAttributeRouteTest.cs @@ -202,8 +202,9 @@ namespace Microsoft.AspNet.Mvc.Routing [InlineData("template/{parameter:int}", "/template/5", true)] [InlineData("template/{parameter:int?}", "/template/5", true)] [InlineData("template/{parameter:int?}", "/template", true)] - [InlineData("template/{parameter:int?}", "/template/qwer", false)] - public async Task AttributeRoute_WithOptionalInlineConstraint(string template, string request, bool expectedResult) + [InlineData("template/{parameter:int?}", "/template/qwer", false)] + public async Task AttributeRoute_WithOptionalInlineConstraint( + string template, string request, bool expectedResult) { // Arrange var expectedRouteGroup = string.Format("{0}&&{1}", 0, template); @@ -245,7 +246,7 @@ namespace Microsoft.AspNet.Mvc.Routing } } - [Theory] + [Theory] [InlineData("moo/{p1}.{p2?}", "/moo/foo.bar", "foo", "bar", null)] [InlineData("moo/{p1?}", "/moo/foo", "foo", null, null)] [InlineData("moo/{p1?}", "/moo", null, null, null)] @@ -255,7 +256,7 @@ namespace Microsoft.AspNet.Mvc.Routing [InlineData("moo/{p1}.{p2}", "/moo/foo.bar", "foo", "bar", null)] [InlineData("moo/foo.{p1}.{p2?}", "/moo/foo.moo.bar", "moo", "bar", null)] [InlineData("moo/foo.{p1}.{p2?}", "/moo/foo.moo", "moo", null, null)] - [InlineData("moo/.{p2?}", "/moo/.foo", null, "foo", null)] + [InlineData("moo/.{p2?}", "/moo/.foo", null, "foo", null)] [InlineData("moo/{p1}.{p2?}", "/moo/....", "..", ".", null)] [InlineData("moo/{p1}.{p2?}", "/moo/.bar", ".bar", null, null)] [InlineData("moo/{p1}.{p2}.{p3?}", "/moo/foo.moo.bar", "foo", "moo", "bar")] @@ -265,8 +266,8 @@ namespace Microsoft.AspNet.Mvc.Routing [InlineData("{p1}.{p2?}/{p3}", "/foo/bar", "foo", null, "bar")] [InlineData("{p1}.{p2?}/{p3}", "/.foo/bar", ".foo", null, "bar")] public async Task AttributeRoute_WithOptionalCompositeParameter_Valid( - string template, - string request, + string template, + string request, string p1, string p2, string p3) @@ -296,7 +297,7 @@ namespace Microsoft.AspNet.Mvc.Routing // Act await route.RouteAsync(context); - // Assert + // Assert Assert.True(context.IsHandled); if (p1 != null) { @@ -355,8 +356,8 @@ namespace Microsoft.AspNet.Mvc.Routing // Act await route.RouteAsync(context); - // Assert - Assert.False(context.IsHandled); + // Assert + Assert.False(context.IsHandled); } [Theory] @@ -383,7 +384,7 @@ namespace Microsoft.AspNet.Mvc.Routing selectedGroup = (string)ctx.ProvidedValues[AttributeRouting.RouteGroupKey]; ctx.IsBound = true; }) - .Returns((string)null); + .Returns((VirtualPathData)null); var matchingRoutes = Enumerable.Empty(); @@ -399,11 +400,14 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(values: null, ambientValues: new { parameter = 5 }); // Act - string result = route.GetVirtualPath(context); + var result = route.GetVirtualPath(context); // Assert Assert.NotNull(result); - Assert.Equal("template/5", result); + Assert.Equal("template/5", result.VirtualPath); + Assert.Same(route, result.Router); + Assert.Empty(result.DataTokens); + Assert.Equal(expectedGroup, selectedGroup); } @@ -417,7 +421,8 @@ namespace Microsoft.AspNet.Mvc.Routing [InlineData("template/{parameter:int:range(1,20)?}", "template", null)] [InlineData("template/{parameter:int:range(1,20)?}", "template/5", 5)] [InlineData("template/{parameter:int:range(1,20)?}", null, 21)] - public void AttributeRoute_GenerateLink_OptionalInlineParameter(string template, string expectedResult, object parameter) + public void AttributeRoute_GenerateLink_OptionalInlineParameter + (string template, string expectedPath, object parameter) { // Arrange var expectedGroup = CreateRouteGroup(0, template); @@ -430,7 +435,7 @@ namespace Microsoft.AspNet.Mvc.Routing selectedGroup = (string)ctx.ProvidedValues[AttributeRouting.RouteGroupKey]; ctx.IsBound = true; }) - .Returns((string)null); + .Returns((VirtualPathData)null); var matchingRoutes = Enumerable.Empty(); @@ -451,10 +456,20 @@ namespace Microsoft.AspNet.Mvc.Routing } // Act - string result = route.GetVirtualPath(context); + var result = route.GetVirtualPath(context); - // Assert - Assert.Equal(expectedResult, result); + // Assert + if (expectedPath == null) + { + Assert.Null(result); + } + else + { + Assert.NotNull(result); + Assert.Equal(expectedPath, result.VirtualPath); + Assert.Same(route, result.Router); + Assert.Empty(result.DataTokens); + } } [Theory] @@ -480,7 +495,7 @@ namespace Microsoft.AspNet.Mvc.Routing firstRouteGroupSelected = (string)ctx.ProvidedValues[AttributeRouting.RouteGroupKey]; ctx.IsBound = true; }) - .Returns((string)null); + .Returns((VirtualPathData)null); var matchingRoutes = Enumerable.Empty(); @@ -497,11 +512,14 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(null, ambientValues: new { parameter = 5 }); // Act - string result = route.GetVirtualPath(context); + var result = route.GetVirtualPath(context); // Assert Assert.NotNull(result); - Assert.Equal("template/5", result); + Assert.Equal("template/5", result.VirtualPath); + Assert.Same(route, result.Router); + Assert.Empty(result.DataTokens); + Assert.Equal(selectedGroup, firstRouteGroupSelected); } @@ -523,7 +541,7 @@ namespace Microsoft.AspNet.Mvc.Routing selectedGroup = (string)ctx.ProvidedValues[AttributeRouting.RouteGroupKey]; ctx.IsBound = true; }) - .Returns((string)null); + .Returns((VirtualPathData)null); var matchingRoutes = Enumerable.Empty(); @@ -539,11 +557,14 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(values: null, ambientValues: new { first = 5, second = 5 }); // Act - string result = route.GetVirtualPath(context); + var result = route.GetVirtualPath(context); // Assert Assert.NotNull(result); - Assert.Equal("template/5", result); + Assert.Equal("template/5", result.VirtualPath); + Assert.Same(route, result.Router); + Assert.Empty(result.DataTokens); + Assert.Equal(expectedGroup, selectedGroup); } @@ -565,7 +586,7 @@ namespace Microsoft.AspNet.Mvc.Routing selectedGroup = (string)ctx.ProvidedValues[AttributeRouting.RouteGroupKey]; ctx.IsBound = true; }) - .Returns((string)null); + .Returns((VirtualPathData)null); var matchingRoutes = Enumerable.Empty(); @@ -581,11 +602,14 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(values: null, ambientValues: new { first = 5, second = 5 }); // Act - string result = route.GetVirtualPath(context); + var result = route.GetVirtualPath(context); // Assert Assert.NotNull(result); - Assert.Equal("first/5", result); + Assert.Equal("first/5", result.VirtualPath); + Assert.Same(route, result.Router); + Assert.Empty(result.DataTokens); + Assert.Equal(expectedGroup, selectedGroup); } @@ -696,7 +720,8 @@ namespace Microsoft.AspNet.Mvc.Routing { vpc.IsBound = true; selectedGroup = (string)vpc.ProvidedValues[AttributeRouting.RouteGroupKey]; - }); + }) + .Returns((VirtualPathData)null); var matchingEntries = Enumerable.Empty(); @@ -711,8 +736,11 @@ namespace Microsoft.AspNet.Mvc.Routing // Assert Assert.NotNull(result); + Assert.Equal(expectedLink, result.VirtualPath); + Assert.Same(route, result.Router); + Assert.Empty(result.DataTokens); + Assert.Equal(expectedGroup, selectedGroup); - Assert.Equal(expectedLink, result); } [Fact] @@ -726,7 +754,8 @@ namespace Microsoft.AspNet.Mvc.Routing { vpc.IsBound = true; selectedGroup = (string)vpc.ProvidedValues[AttributeRouting.RouteGroupKey]; - }); + }) + .Returns((VirtualPathData)null); var namedEntry = CreateGenerationEntry("named", requiredValues: null, order: 1, name: "NamedRoute"); var unnamedEntry = CreateGenerationEntry("unnamed", requiredValues: null, order: 0); @@ -746,8 +775,11 @@ namespace Microsoft.AspNet.Mvc.Routing // Assert Assert.NotNull(result); + Assert.Equal("named", result.VirtualPath); + Assert.Same(route, result.Router); + Assert.Empty(result.DataTokens); + Assert.Equal("1&named", selectedGroup); - Assert.Equal("named", result); } [Fact] @@ -842,7 +874,8 @@ namespace Microsoft.AspNet.Mvc.Routing { vpc.IsBound = true; selectedGroup = (string)vpc.ProvidedValues[AttributeRouting.RouteGroupKey]; - }); + }) + .Returns((VirtualPathData)null); var namedEntry = CreateGenerationEntry(template, requiredValues: null, order: 1, name: "NamedRoute"); @@ -866,8 +899,11 @@ namespace Microsoft.AspNet.Mvc.Routing // Assert Assert.NotNull(result); + Assert.Equal("template/5", result.VirtualPath); + Assert.Same(route, result.Router); + Assert.Empty(result.DataTokens); + Assert.Equal(string.Format("1&{0}", template), selectedGroup); - Assert.Equal("template/5", result); } [Fact] @@ -942,10 +978,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api/Store", path); + Assert.NotNull(pathData); + Assert.Equal("api/Store", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -958,10 +997,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { action = "Index", controller = "Store" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api/Store", path); + Assert.NotNull(pathData); + Assert.Equal("api/Store", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -990,10 +1032,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { }, new { action = "Index", controller = "Store" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api/Store", path); + Assert.NotNull(pathData); + Assert.Equal("api/Store", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -1006,10 +1051,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { action = "Index", controller = "Store" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api/Store/Index", path); + Assert.NotNull(pathData); + Assert.Equal("api/Store/Index", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -1036,10 +1084,14 @@ namespace Microsoft.AspNet.Mvc.Routing new { area = "AwesomeCo" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api/AwesomeCo/dosomething/Store/Index", path); + Assert.NotNull(pathData); + Assert.Equal("api/AwesomeCo/dosomething/Store/Index", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); + Assert.Equal(expectedValues, next.GenerationContext.ProvidedValues); } @@ -1053,10 +1105,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { action = "Index", controller = "Store" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api/Store", path); + Assert.NotNull(pathData); + Assert.Equal("api/Store", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -1078,10 +1133,14 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { action = "Index", controller = "Store", id = 5 }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api/Store/Index/5", path); + Assert.NotNull(pathData); + Assert.Equal("api/Store/Index/5", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); + Assert.Equal(expectedValues, next.GenerationContext.ProvidedValues); } @@ -1118,10 +1177,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { action = "Index" }, new { controller = "Store" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api/Store", path); + Assert.NotNull(pathData); + Assert.Equal("api/Store", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -1134,10 +1196,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { action = "Index", id = 5 }, new { controller = "Store" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api/Store?id=5", path); + Assert.NotNull(pathData); + Assert.Equal("api/Store?id=5", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -1175,10 +1240,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { action = "Index", controller = "Blog" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api2/Blog", path); + Assert.NotNull(pathData); + Assert.Equal("api2/Blog", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -1205,10 +1273,14 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { action = "Edit", controller = "Store" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("api2/Store", path); + Assert.NotNull(pathData); + Assert.Equal("api2/Store", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); + Assert.Equal(2, callCount); } @@ -1229,10 +1301,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { area = "Help", action = "Edit", controller = "Store" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("Help/Store", path); + Assert.NotNull(pathData); + Assert.Equal("Help/Store", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -1252,10 +1327,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(new { area = "Help", action = "Edit", controller = "Store" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("Help/Store", path); + Assert.NotNull(pathData); + Assert.Equal("Help/Store", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -1277,10 +1355,13 @@ namespace Microsoft.AspNet.Mvc.Routing ambientValues: new { area = "Help" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("Help/Store", path); + Assert.NotNull(pathData); + Assert.Equal("Help/Store", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -1302,10 +1383,13 @@ namespace Microsoft.AspNet.Mvc.Routing ambientValues: new { area = "Blog" }); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal("Store", path); + Assert.NotNull(pathData); + Assert.Equal("Store", pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } public static IEnumerable OptionalParamValues @@ -1392,10 +1476,13 @@ namespace Microsoft.AspNet.Mvc.Routing var context = CreateVirtualPathContext(values, ambientValues); // Act - var path = route.GetVirtualPath(context); + var pathData = route.GetVirtualPath(context); // Assert - Assert.Equal(expected, path); + Assert.NotNull(pathData); + Assert.Equal(expected, pathData.VirtualPath); + Assert.Same(route, pathData.Router); + Assert.Empty(pathData.DataTokens); } [Fact] @@ -1725,7 +1812,7 @@ namespace Microsoft.AspNet.Mvc.Routing public Func MatchingDelegate { get; set; } - public string GetVirtualPath(VirtualPathContext context) + public VirtualPathData GetVirtualPath(VirtualPathContext context) { GenerationContext = context; diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/UrlHelperTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/UrlHelperTest.cs index 791ad5b921..333f512f1f 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/UrlHelperTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/UrlHelperTest.cs @@ -923,7 +923,7 @@ namespace Microsoft.AspNet.Mvc private static IRouter GetRouter( - IServiceProvider services, + IServiceProvider services, string mockRouteName, string mockTemplateValue) { @@ -949,7 +949,7 @@ namespace Microsoft.AspNet.Mvc mockHttpRoute .Setup(mock => mock.GetVirtualPath(It.Is(c => string.Equals(c.RouteName, mockRouteName)))) .Callback(c => c.IsBound = true) - .Returns(mockTemplateValue); + .Returns(new VirtualPathData(mockHttpRoute.Object, mockTemplateValue)); routeBuilder.Routes.Add(mockHttpRoute.Object); return routeBuilder.Build(); diff --git a/test/WebSites/CustomRouteWebSite/LocalizedRoute.cs b/test/WebSites/CustomRouteWebSite/LocalizedRoute.cs index 638a0e96d7..5e59b488ef 100644 --- a/test/WebSites/CustomRouteWebSite/LocalizedRoute.cs +++ b/test/WebSites/CustomRouteWebSite/LocalizedRoute.cs @@ -24,7 +24,7 @@ namespace CustomRouteWebSite _next = next; } - public string GetVirtualPath(VirtualPathContext context) + public VirtualPathData GetVirtualPath(VirtualPathContext context) { // We just want to act as a pass-through for link generation return _next.GetVirtualPath(context);