[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;
|
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 });
|
current.Matches.Add(new InboundMatch() { Entry = entry, TemplateMatcher = matcher });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ using Microsoft.Extensions.Options;
|
||||||
using Microsoft.Extensions.WebEncoders.Testing;
|
using Microsoft.Extensions.WebEncoders.Testing;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using Xunit.Extensions;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Routing.Tree
|
namespace Microsoft.AspNetCore.Routing.Tree
|
||||||
{
|
{
|
||||||
|
|
@ -125,6 +126,153 @@ namespace Microsoft.AspNetCore.Routing.Tree
|
||||||
Assert.Equal(expectedRouteGroup, context.RouteData.Values["test_route_group"]);
|
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]
|
[Fact]
|
||||||
public async Task TreeRouter_RouteAsync_DoesNotMatchShorterUrl()
|
public async Task TreeRouter_RouteAsync_DoesNotMatchShorterUrl()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue