[Fixes #324] Default parameters are not taken into account on attribute routing
This commit is contained in:
parent
0978a7dd16
commit
90dc4bc207
|
|
@ -333,7 +333,7 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
continue;
|
||||
}
|
||||
|
||||
if (part.IsParameter && (part.IsOptional || part.IsCatchAll))
|
||||
if (part.IsParameter && (part.IsOptional || part.IsCatchAll || part.DefaultValue != null))
|
||||
{
|
||||
current.Matches.Add(new InboundMatch() { Entry = entry, TemplateMatcher = matcher });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ using Microsoft.Extensions.Options;
|
|||
using Microsoft.Extensions.WebEncoders.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Xunit.Extensions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Routing.Tree
|
||||
{
|
||||
|
|
@ -125,6 +126,153 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
|||
Assert.Equal(expectedRouteGroup, context.RouteData.Values["test_route_group"]);
|
||||
}
|
||||
|
||||
public static TheoryData<string, object[]> MatchesRoutesWithDefaultsData =>
|
||||
new TheoryData<string, object[]>
|
||||
{
|
||||
{ "/", new object[] { "1", "2", "3", "4" } },
|
||||
{ "/a", new object[] { "a", "2", "3", "4" } },
|
||||
{ "/a/b", new object[] { "a", "b", "3", "4" } },
|
||||
{ "/a/b/c", new object[] { "a", "b", "c", "4" } },
|
||||
{ "/a/b/c/d", new object[] { "a", "b", "c", "d" } }
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(MatchesRoutesWithDefaultsData))]
|
||||
public async Task TreeRouter_RouteAsync_MatchesRoutesWithDefaults(string url, object[] routeValues)
|
||||
{
|
||||
// Arrange
|
||||
var routes = new[] {
|
||||
"{parameter1=1}/{parameter2=2}/{parameter3=3}/{parameter4=4}",
|
||||
};
|
||||
|
||||
var expectedRouteGroup = CreateRouteGroup(0, "{parameter1=1}/{parameter2=2}/{parameter3=3}/{parameter4=4}");
|
||||
var routeValueKeys = new[] { "parameter1", "parameter2", "parameter3", "parameter4" };
|
||||
var expectedRouteValues = new RouteValueDictionary();
|
||||
for (int i = 0; i < routeValueKeys.Length; i++)
|
||||
{
|
||||
expectedRouteValues.Add(routeValueKeys[i], routeValues[i]);
|
||||
}
|
||||
|
||||
var builder = CreateBuilder();
|
||||
|
||||
// We setup the route entries in reverse order of precedence to ensure that when we
|
||||
// try to route the request, the route with a higher precedence gets tried first.
|
||||
foreach (var template in routes.Reverse())
|
||||
{
|
||||
MapInboundEntry(builder, template);
|
||||
}
|
||||
|
||||
var route = builder.Build();
|
||||
|
||||
var context = CreateRouteContext(url);
|
||||
|
||||
// Act
|
||||
await route.RouteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedRouteGroup, context.RouteData.Values["test_route_group"]);
|
||||
foreach (var entry in expectedRouteValues)
|
||||
{
|
||||
var data = Assert.Single(context.RouteData.Values, v => v.Key == entry.Key);
|
||||
Assert.Equal(entry.Value, data.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public static TheoryData<string, object[]> MatchesConstrainedRoutesWithDefaultsData =>
|
||||
new TheoryData<string, object[]>
|
||||
{
|
||||
{ "/", new object[] { "1", "2", "3", "4" } },
|
||||
{ "/10", new object[] { "10", "2", "3", "4" } },
|
||||
{ "/10/11", new object[] { "10", "11", "3", "4" } },
|
||||
{ "/10/11/12", new object[] { "10", "11", "12", "4" } },
|
||||
{ "/10/11/12/13", new object[] { "10", "11", "12", "13" } }
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(MatchesConstrainedRoutesWithDefaultsData))]
|
||||
public async Task TreeRouter_RouteAsync_MatchesConstrainedRoutesWithDefaults(string url, object[] routeValues)
|
||||
{
|
||||
// Arrange
|
||||
var routes = new[] {
|
||||
"{parameter1:int=1}/{parameter2:int=2}/{parameter3:int=3}/{parameter4:int=4}",
|
||||
};
|
||||
|
||||
var expectedRouteGroup = CreateRouteGroup(0, "{parameter1:int=1}/{parameter2:int=2}/{parameter3:int=3}/{parameter4:int=4}");
|
||||
var routeValueKeys = new[] { "parameter1", "parameter2", "parameter3", "parameter4" };
|
||||
var expectedRouteValues = new RouteValueDictionary();
|
||||
for (int i = 0; i < routeValueKeys.Length; i++)
|
||||
{
|
||||
expectedRouteValues.Add(routeValueKeys[i], routeValues[i]);
|
||||
}
|
||||
|
||||
var builder = CreateBuilder();
|
||||
|
||||
// We setup the route entries in reverse order of precedence to ensure that when we
|
||||
// try to route the request, the route with a higher precedence gets tried first.
|
||||
foreach (var template in routes.Reverse())
|
||||
{
|
||||
MapInboundEntry(builder, template);
|
||||
}
|
||||
|
||||
var route = builder.Build();
|
||||
|
||||
var context = CreateRouteContext(url);
|
||||
|
||||
// Act
|
||||
await route.RouteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedRouteGroup, context.RouteData.Values["test_route_group"]);
|
||||
foreach (var entry in expectedRouteValues)
|
||||
{
|
||||
var data = Assert.Single(context.RouteData.Values, v => v.Key == entry.Key);
|
||||
Assert.Equal(entry.Value, data.Value);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TreeRouter_RouteAsync_MatchesCatchAllRoutesWithDefaults()
|
||||
{
|
||||
// Arrange
|
||||
var routes = new[] {
|
||||
"{parameter1=1}/{parameter2=2}/{parameter3=3}/{*parameter4=4}",
|
||||
};
|
||||
var url = "/a/b/c";
|
||||
var routeValues = new[] { "a", "b", "c", "4" };
|
||||
|
||||
var expectedRouteGroup = CreateRouteGroup(0, "{parameter1=1}/{parameter2=2}/{parameter3=3}/{*parameter4=4}");
|
||||
var routeValueKeys = new[] { "parameter1", "parameter2", "parameter3", "parameter4" };
|
||||
var expectedRouteValues = new RouteValueDictionary();
|
||||
for (int i = 0; i < routeValueKeys.Length; i++)
|
||||
{
|
||||
expectedRouteValues.Add(routeValueKeys[i], routeValues[i]);
|
||||
}
|
||||
|
||||
var builder = CreateBuilder();
|
||||
|
||||
// We setup the route entries in reverse order of precedence to ensure that when we
|
||||
// try to route the request, the route with a higher precedence gets tried first.
|
||||
foreach (var template in routes.Reverse())
|
||||
{
|
||||
MapInboundEntry(builder, template);
|
||||
}
|
||||
|
||||
var route = builder.Build();
|
||||
|
||||
var context = CreateRouteContext(url);
|
||||
|
||||
// Act
|
||||
await route.RouteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedRouteGroup, context.RouteData.Values["test_route_group"]);
|
||||
foreach (var entry in expectedRouteValues)
|
||||
{
|
||||
var data = Assert.Single(context.RouteData.Values, v => v.Key == entry.Key);
|
||||
Assert.Equal(entry.Value, data.Value);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TreeRouter_RouteAsync_DoesNotMatchShorterUrl()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue