Merge branch 'rel/1.1.1' into dev
# Conflicts: # NuGet.config # samples/RoutingSample.Web/project.json # src/Microsoft.AspNetCore.Routing.Abstractions/project.json # src/Microsoft.AspNetCore.Routing.DecisionTree.Sources/project.json # src/Microsoft.AspNetCore.Routing/project.json # test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/project.json # test/Microsoft.AspNetCore.Routing.DecisionTree.Sources.Tests/project.json # test/Microsoft.AspNetCore.Routing.FunctionalTests/project.json # test/Microsoft.AspNetCore.Routing.Tests/project.json
This commit is contained in:
commit
071b616178
|
|
@ -171,8 +171,7 @@ namespace Microsoft.AspNetCore.Routing.Template
|
||||||
|
|
||||||
// Add any ambient values that don't match parameters - they need to be visible to constraints
|
// Add any ambient values that don't match parameters - they need to be visible to constraints
|
||||||
// but they will ignored by link generation.
|
// but they will ignored by link generation.
|
||||||
// Perf: Lazily allocate RouteValueDictionary only when needed as in most cases combined is same as accepted values
|
var combinedValues = new RouteValueDictionary(context.AcceptedValues);
|
||||||
RouteValueDictionary combinedValues = null;
|
|
||||||
if (ambientValues != null)
|
if (ambientValues != null)
|
||||||
{
|
{
|
||||||
foreach (var kvp in ambientValues)
|
foreach (var kvp in ambientValues)
|
||||||
|
|
@ -182,10 +181,6 @@ namespace Microsoft.AspNetCore.Routing.Template
|
||||||
var parameter = GetParameter(kvp.Key);
|
var parameter = GetParameter(kvp.Key);
|
||||||
if (parameter == null && !context.AcceptedValues.ContainsKey(kvp.Key))
|
if (parameter == null && !context.AcceptedValues.ContainsKey(kvp.Key))
|
||||||
{
|
{
|
||||||
if (combinedValues == null)
|
|
||||||
{
|
|
||||||
combinedValues = new RouteValueDictionary(context.AcceptedValues);
|
|
||||||
}
|
|
||||||
combinedValues.Add(kvp.Key, kvp.Value);
|
combinedValues.Add(kvp.Key, kvp.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +190,7 @@ namespace Microsoft.AspNetCore.Routing.Template
|
||||||
return new TemplateValuesResult()
|
return new TemplateValuesResult()
|
||||||
{
|
{
|
||||||
AcceptedValues = context.AcceptedValues,
|
AcceptedValues = context.AcceptedValues,
|
||||||
CombinedValues = combinedValues ?? context.AcceptedValues
|
CombinedValues = combinedValues,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -363,6 +363,61 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
Assert.Empty(pathData.DataTokens);
|
Assert.Empty(pathData.DataTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<object[]> RestoresRouteDataForEachRouterData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// Here 'area' segment doesn't have a value but the later segments have values. This is an invalid
|
||||||
|
// route match and the url generation should look into the next available route in the collection.
|
||||||
|
yield return new object[] {
|
||||||
|
new Route[]
|
||||||
|
{
|
||||||
|
CreateTemplateRoute("{area?}/{controller=Home}/{action=Index}/{id?}", "1"),
|
||||||
|
CreateTemplateRoute("{controller=Home}/{action=Index}/{id?}", "2")
|
||||||
|
},
|
||||||
|
new RouteValueDictionary(new { controller = "Test", action = "Index" }),
|
||||||
|
"/Test",
|
||||||
|
"2" };
|
||||||
|
|
||||||
|
// Here the segment 'a' is valid but 'b' is not as it would be empty. This would be an invalid route match, but
|
||||||
|
// the route value of 'a' should still be present to be evaluated for the next available route.
|
||||||
|
yield return new object[] {
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
CreateTemplateRoute("{a}/{b?}/{c}", "1"),
|
||||||
|
CreateTemplateRoute("{a=Home}/{b=Index}", "2")
|
||||||
|
},
|
||||||
|
new RouteValueDictionary(new { a = "Test", c = "Foo" }),
|
||||||
|
"/Test?c=Foo",
|
||||||
|
"2" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(RestoresRouteDataForEachRouterData))]
|
||||||
|
public void GetVirtualPath_RestoresRouteData_ForEachRouter(
|
||||||
|
Route[] routes,
|
||||||
|
RouteValueDictionary routeValues,
|
||||||
|
string expectedUrl,
|
||||||
|
string expectedRouteToMatch)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var routeCollection = new RouteCollection();
|
||||||
|
foreach (var route in routes)
|
||||||
|
{
|
||||||
|
routeCollection.Add(route);
|
||||||
|
}
|
||||||
|
var context = CreateVirtualPathContext(routeValues);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var pathData = routeCollection.GetVirtualPath(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedUrl, pathData.VirtualPath);
|
||||||
|
Assert.Same(expectedRouteToMatch, ((INamedRouter)pathData.Router).Name);
|
||||||
|
Assert.Empty(pathData.DataTokens);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetVirtualPath_NoBestEffort_NoMatch()
|
public void GetVirtualPath_NoBestEffort_NoMatch()
|
||||||
{
|
{
|
||||||
|
|
@ -496,14 +551,18 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
private static Route CreateTemplateRoute(
|
private static Route CreateTemplateRoute(
|
||||||
string template,
|
string template,
|
||||||
string routerName = null,
|
string routerName = null,
|
||||||
RouteValueDictionary dataTokens = null)
|
RouteValueDictionary dataTokens = null,
|
||||||
|
IInlineConstraintResolver constraintResolver = null)
|
||||||
{
|
{
|
||||||
var target = new Mock<IRouter>(MockBehavior.Strict);
|
var target = new Mock<IRouter>(MockBehavior.Strict);
|
||||||
target
|
target
|
||||||
.Setup(e => e.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
.Setup(e => e.GetVirtualPath(It.IsAny<VirtualPathContext>()))
|
||||||
.Returns<VirtualPathContext>(rc => null);
|
.Returns<VirtualPathContext>(rc => null);
|
||||||
|
|
||||||
var resolverMock = new Mock<IInlineConstraintResolver>();
|
if (constraintResolver == null)
|
||||||
|
{
|
||||||
|
constraintResolver = new Mock<IInlineConstraintResolver>().Object;
|
||||||
|
}
|
||||||
|
|
||||||
return new Route(
|
return new Route(
|
||||||
target.Object,
|
target.Object,
|
||||||
|
|
@ -512,7 +571,7 @@ namespace Microsoft.AspNetCore.Routing
|
||||||
defaults: null,
|
defaults: null,
|
||||||
constraints: null,
|
constraints: null,
|
||||||
dataTokens: dataTokens,
|
dataTokens: dataTokens,
|
||||||
inlineConstraintResolver: resolverMock.Object);
|
inlineConstraintResolver: constraintResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static VirtualPathContext CreateVirtualPathContext(
|
private static VirtualPathContext CreateVirtualPathContext(
|
||||||
|
|
|
||||||
|
|
@ -691,6 +691,34 @@ namespace Microsoft.AspNetCore.Routing.Template.Tests
|
||||||
"/UrlEncode[[v1]]");
|
"/UrlEncode[[v1]]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TemplateBinder_KeepsExplicitlySuppliedRouteValues_OnFailedRouetMatch()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var template = "{area?}/{controller=Home}/{action=Index}/{id?}";
|
||||||
|
var encoder = new UrlTestEncoder();
|
||||||
|
var binder = new TemplateBinder(
|
||||||
|
new UrlTestEncoder(),
|
||||||
|
new DefaultObjectPoolProvider().Create(new UriBuilderContextPooledObjectPolicy(encoder)),
|
||||||
|
TemplateParser.Parse(template),
|
||||||
|
defaults: null);
|
||||||
|
var ambientValues = new RouteValueDictionary();
|
||||||
|
var routeValues = new RouteValueDictionary(new { controller = "Test", action = "Index" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var templateValuesResult = binder.GetValues(ambientValues, routeValues);
|
||||||
|
var boundTemplate = binder.BindValues(templateValuesResult.AcceptedValues);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Null(boundTemplate);
|
||||||
|
Assert.Equal(2, templateValuesResult.CombinedValues.Count);
|
||||||
|
object routeValue;
|
||||||
|
Assert.True(templateValuesResult.CombinedValues.TryGetValue("controller", out routeValue));
|
||||||
|
Assert.Equal("Test", routeValue?.ToString());
|
||||||
|
Assert.True(templateValuesResult.CombinedValues.TryGetValue("action", out routeValue));
|
||||||
|
Assert.Equal("Index", routeValue?.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
#if ROUTE_COLLECTION
|
#if ROUTE_COLLECTION
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue