Implement IRoutingFeature on EndpointFeature for back-compat (#641)

This commit is contained in:
James Newton-King 2018-07-20 18:23:14 +12:00 committed by GitHub
parent 41f56dbbed
commit 90395c933d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 3 deletions

View File

@ -51,6 +51,20 @@ namespace Microsoft.AspNetCore.Routing
}
}
/// <summary>
/// Creates a new <see cref="RouteData"/> instance with the specified values.
/// </summary>
/// <param name="values">The <see cref="RouteValueDictionary"/> values.</param>
public RouteData(RouteValueDictionary values)
{
if (values == null)
{
throw new ArgumentNullException(nameof(values));
}
_values = values;
}
/// <summary>
/// Gets the data tokens produced by routes on the current routing path.
/// </summary>
@ -84,7 +98,7 @@ namespace Microsoft.AspNetCore.Routing
}
/// <summary>
/// Gets the set of values produced by routes on the current routing path.
/// Gets the values produced by routes on the current routing path.
/// </summary>
public RouteValueDictionary Values
{

View File

@ -57,6 +57,9 @@ namespace Microsoft.AspNetCore.Routing
var feature = new EndpointFeature();
httpContext.Features.Set<IEndpointFeature>(feature);
// Back compat support for users of IRoutingFeature
httpContext.Features.Set<IRoutingFeature>(feature);
// There's an inherent race condition between waiting for init and accessing the matcher
// this is OK because once `_matcher` is initialized, it will not be set to null again.
var matcher = await InitializeAsync();

View File

@ -6,12 +6,39 @@ using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Routing
{
public sealed class EndpointFeature : IEndpointFeature
public sealed class EndpointFeature : IEndpointFeature, IRoutingFeature
{
private RouteData _routeData;
private RouteValueDictionary _values;
public Endpoint Endpoint { get; set; }
public Func<RequestDelegate, RequestDelegate> Invoker { get; set; }
public RouteValueDictionary Values { get; set; }
public RouteValueDictionary Values
{
get => _values;
set
{
_values = value;
// RouteData will be created next get with new Values
_routeData = null;
}
}
RouteData IRoutingFeature.RouteData
{
get
{
if (_routeData == null)
{
_routeData = new RouteData(_values);
}
return _routeData;
}
set => throw new NotSupportedException();
}
}
}

View File

@ -58,6 +58,30 @@ namespace Microsoft.AspNetCore.Routing
Assert.Equal(expectedMessage, write.State?.ToString());
}
[Fact]
public async Task Invoke_BackCompatGetRouteValue_ValueUsedFromEndpointFeature()
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.RequestServices = new TestServiceProvider();
var middleware = CreateMiddleware();
// Act
await middleware.Invoke(httpContext);
var routeData = httpContext.GetRouteData();
var routeValue = httpContext.GetRouteValue("controller");
var endpointFeature = httpContext.Features.Get<IEndpointFeature>();
// Assert
Assert.NotNull(routeData);
Assert.Equal("Home", (string)routeValue);
// changing route data value is reflected in endpoint feature values
routeData.Values["testKey"] = "testValue";
Assert.Equal("testValue", endpointFeature.Values["testKey"]);
}
private DispatcherMiddleware CreateMiddleware(Logger<DispatcherMiddleware> logger = null)
{
RequestDelegate next = (c) => Task.FromResult<object>(null);

View File

@ -20,6 +20,7 @@ namespace Microsoft.AspNetCore.Routing.TestObjects
{
if (_isHandled)
{
feature.Values = new RouteValueDictionary(new { controller = "Home", action = "Index" });
feature.Endpoint = new TestEndpoint(EndpointMetadataCollection.Empty, "Test endpoint");
}