Merge branch 'dotnet-maestro-bot-merge/release/2.2-to-master'

This commit is contained in:
Ryan Nowak 2018-09-03 11:43:23 -07:00
commit ca681138e3
5 changed files with 111 additions and 40 deletions

View File

@ -38,8 +38,8 @@
<MoqPackageVersion>4.7.49</MoqPackageVersion>
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
<SystemReflectionEmitPackageVersion>4.3.0</SystemReflectionEmitPackageVersion>
<SystemReflectionEmitLightweightPackageVersion>4.3.0</SystemReflectionEmitLightweightPackageVersion>
<SystemReflectionEmitPackageVersion>4.3.0</SystemReflectionEmitPackageVersion>
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
<XunitPackageVersion>2.3.1</XunitPackageVersion>
<XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>

View File

@ -32,26 +32,18 @@ namespace Microsoft.AspNetCore.Routing
public async Task Invoke(HttpContext httpContext)
{
var feature = httpContext.Features.Get<IEndpointFeature>();
if (feature == null)
var endpoint = httpContext.Features.Get<IEndpointFeature>()?.Endpoint;
if (endpoint?.RequestDelegate != null)
{
var message = $"Unable to execute an endpoint because the {nameof(EndpointRoutingMiddleware)} was not run for this request. " +
$"Ensure {nameof(EndpointRoutingMiddleware)} is added to the request execution pipeline before {nameof(EndpointMiddleware)} in application startup code.";
throw new InvalidOperationException(message);
}
if (feature.Endpoint?.RequestDelegate != null)
{
Log.ExecutingEndpoint(_logger, feature.Endpoint);
Log.ExecutingEndpoint(_logger, endpoint);
try
{
await feature.Endpoint.RequestDelegate(httpContext);
await endpoint.RequestDelegate(httpContext);
}
finally
{
Log.ExecutedEndpoint(_logger, feature.Endpoint);
Log.ExecutedEndpoint(_logger, endpoint);
}
return;

View File

@ -55,11 +55,8 @@ namespace Microsoft.AspNetCore.Routing
public async Task Invoke(HttpContext httpContext)
{
// For back-compat EndpointRouteValuesFeature implements IEndpointFeature, IRouteValuesFeature and IRoutingFeature
var feature = new EndpointFeature();
SetEndpointFeature(httpContext, 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();
@ -67,6 +64,10 @@ namespace Microsoft.AspNetCore.Routing
await matcher.MatchAsync(httpContext, feature);
if (feature.Endpoint != null)
{
// Set the endpoint feature only on success. This means we won't overwrite any
// existing state for related features unless we did something.
SetEndpointFeature(httpContext, feature);
Log.MatchSuccess(_logger, feature);
}
else
@ -79,11 +80,8 @@ namespace Microsoft.AspNetCore.Routing
private static void SetEndpointFeature(HttpContext httpContext, EndpointFeature feature)
{
// An IRouteValuesFeature might have already been set
// Copy its RouteValues collection if present
var currentRouteValuesFeature = httpContext.Features.Get<IRouteValuesFeature>();
feature.RouteValues = currentRouteValuesFeature?.RouteValues;
// For back-compat EndpointRouteValuesFeature implements IEndpointFeature,
// IRouteValuesFeature and IRoutingFeature
httpContext.Features.Set<IRoutingFeature>(feature);
httpContext.Features.Set<IRouteValuesFeature>(feature);
httpContext.Features.Set<IEndpointFeature>(feature);

View File

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Builder.Internal;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;
@ -50,7 +51,7 @@ namespace Microsoft.AspNetCore.Builder
}
[Fact]
public async Task UseEndpointRouting_ServicesRegistered_SetsFeature()
public async Task UseEndpointRouting_ServicesRegistered_NoMatch_DoesNotSetFeature()
{
// Arrange
var services = CreateServices();
@ -66,7 +67,36 @@ namespace Microsoft.AspNetCore.Builder
await appFunc(httpContext);
// Assert
Assert.NotNull(httpContext.Features.Get<IEndpointFeature>());
Assert.Null(httpContext.Features.Get<IEndpointFeature>());
}
[Fact]
public async Task UseEndpointRouting_ServicesRegistered_Match_DoesNotSetsFeature()
{
// Arrange
var endpoint = new RouteEndpoint(
TestConstants.EmptyRequestDelegate,
RoutePatternFactory.Parse("{*p}"),
0,
EndpointMetadataCollection.Empty,
"Test");
var services = CreateServices(endpoint);
var app = new ApplicationBuilder(services);
app.UseEndpointRouting();
var appFunc = app.Build();
var httpContext = new DefaultHttpContext();
// Act
await appFunc(httpContext);
// Assert
var feature = httpContext.Features.Get<IEndpointFeature>();
Assert.NotNull(feature);
Assert.Same(endpoint, feature.Endpoint);
}
[Fact]
@ -89,7 +119,7 @@ namespace Microsoft.AspNetCore.Builder
}
[Fact]
public async Task UseEndpoint_ServicesRegisteredAndEndpointRoutingRegistered_SetsFeature()
public async Task UseEndpoint_ServicesRegisteredAndEndpointRoutingRegistered_NoMatch_DoesNotSetFeature()
{
// Arrange
var services = CreateServices();
@ -106,7 +136,7 @@ namespace Microsoft.AspNetCore.Builder
await appFunc(httpContext);
// Assert
Assert.NotNull(httpContext.Features.Get<IEndpointFeature>());
Assert.Null(httpContext.Features.Get<IEndpointFeature>());
}
[Fact]
@ -129,7 +159,7 @@ namespace Microsoft.AspNetCore.Builder
Assert.Equal("Test endpoint", endpointBuilder.DisplayName);
}
private IServiceProvider CreateServices()
private IServiceProvider CreateServices(params Endpoint[] endpoints)
{
var services = new ServiceCollection();
@ -137,6 +167,8 @@ namespace Microsoft.AspNetCore.Builder
services.AddOptions();
services.AddRouting();
services.AddSingleton<EndpointDataSource>(new DefaultEndpointDataSource(endpoints));
return services.BuildServiceProvider();
}
}

View File

@ -3,11 +3,9 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
namespace Microsoft.AspNetCore.Routing
@ -15,7 +13,7 @@ namespace Microsoft.AspNetCore.Routing
public class EndpointMiddlewareTest
{
[Fact]
public async Task Invoke_NoFeature_ThrowFriendlyErrorMessage()
public async Task Invoke_NoFeature_NoOps()
{
// Arrange
var httpContext = new DefaultHttpContext();
@ -23,22 +21,73 @@ namespace Microsoft.AspNetCore.Routing
RequestDelegate next = (c) =>
{
return Task.FromResult<object>(null);
return Task.CompletedTask;
};
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next);
// Act
var invokeTask = middleware.Invoke(httpContext);
await middleware.Invoke(httpContext);
// Assert - does not throw
}
[Fact]
public async Task Invoke_NoEndpoint_NoOps()
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.RequestServices = new ServiceProvider();
httpContext.Features.Set<IEndpointFeature>(new EndpointFeature()
{
Endpoint = null,
});
RequestDelegate next = (c) =>
{
return Task.CompletedTask;
};
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next);
// Act
await middleware.Invoke(httpContext);
// Assert - does not throw
}
[Fact]
public async Task Invoke_WithEndpoint_InvokesDelegate()
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.RequestServices = new ServiceProvider();
var invoked = false;
RequestDelegate endpointFunc = (c) =>
{
invoked = true;
return Task.CompletedTask;
};
httpContext.Features.Set<IEndpointFeature>(new EndpointFeature()
{
Endpoint = new Endpoint(endpointFunc, EndpointMetadataCollection.Empty, "Test"),
});
RequestDelegate next = (c) =>
{
return Task.CompletedTask;
};
var middleware = new EndpointMiddleware(NullLogger<EndpointMiddleware>.Instance, next);
// Act
await middleware.Invoke(httpContext);
// Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => await invokeTask);
Assert.Equal(
"Unable to execute an endpoint because the EndpointRoutingMiddleware was not run for this request. " +
"Ensure EndpointRoutingMiddleware is added to the request execution pipeline before EndpointMiddleware " +
"in application startup code.",
ex.Message);
Assert.True(invoked);
}
private class ServiceProvider : IServiceProvider