Allow fallback to controller to use MatcherPolicy

This commit is contained in:
Ryan Nowak 2019-04-16 09:58:13 -07:00 committed by Ryan Nowak
parent 4f015e2813
commit 6f305373ca
4 changed files with 39 additions and 4 deletions

View File

@ -14,15 +14,22 @@ namespace Microsoft.AspNetCore.Mvc.Routing
internal class DynamicControllerEndpointMatcherPolicy : MatcherPolicy, IEndpointSelectorPolicy
{
private readonly DynamicControllerEndpointSelector _selector;
private readonly EndpointMetadataComparer _comparer;
public DynamicControllerEndpointMatcherPolicy(DynamicControllerEndpointSelector selector)
public DynamicControllerEndpointMatcherPolicy(DynamicControllerEndpointSelector selector, EndpointMetadataComparer comparer)
{
if (selector == null)
{
throw new ArgumentNullException(nameof(selector));
}
if (comparer == null)
{
throw new ArgumentNullException(nameof(comparer));
}
_selector = selector;
_comparer = comparer;
}
public override int Order => int.MinValue + 100;
@ -99,8 +106,6 @@ namespace Microsoft.AspNetCore.Mvc.Routing
"{ " + string.Join(", ", metadata.Values.Select(kvp => $"{kvp.Key}: {kvp.Value}")) + " }.");
}
var replacement = endpoints[0];
// We need to provide the route values associated with this endpoint, so that features
// like URL generation work.
var values = new RouteValueDictionary(metadata.Values);
@ -111,7 +116,11 @@ namespace Microsoft.AspNetCore.Mvc.Routing
values.TryAdd(kvp.Key, kvp.Value);
}
candidates.ReplaceEndpoint(i, replacement, values);
// Update the route values
candidates.ReplaceEndpoint(i, endpoint, values);
// Expand the list of endpoints
candidates.ExpandEndpoint(i, endpoints, _comparer);
}
return Task.CompletedTask;

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
@ -106,6 +107,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
"{ " + string.Join(", ", metadata.Values.Select(kvp => $"{kvp.Key}: {kvp.Value}")) + " }.");
}
// It should not be possible to have more than one result for pages.
Debug.Assert(endpoints.Count == 1);
var compiled = await _loader.LoadAsync(endpoints[0].Metadata.GetMetadata<PageActionDescriptor>());
var replacement = compiled.Endpoint;

View File

@ -69,6 +69,22 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
Assert.Equal("Hello from fallback controller: /Admin/Fallback", content);
}
[Fact]
public async Task Fallback_CanFallbackToControllerInAreaPost()
{
// Arrange
var url = "http://localhost/Admin/Foo";
var request = new HttpRequestMessage(HttpMethod.Post, url);
// Act
var response = await Client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Hello from fallback controller POST: /Admin/Fallback", content);
}
[Fact]
public async Task Fallback_CanFallbackToPage()
{

View File

@ -12,5 +12,11 @@ namespace RoutingWebSite.Areas.Admin
{
return Content("Hello from fallback controller: " + Url.Action());
}
[HttpPost]
public ActionResult Index(int x)
{
return Content("Hello from fallback controller POST: " + Url.Action());
}
}
}