Check dispatcher services registered (#610)
This commit is contained in:
parent
5e1f99faaf
commit
73e4d55d7b
|
|
@ -1,7 +1,10 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.AspNetCore.Routing.Internal;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Builder
|
namespace Microsoft.AspNetCore.Builder
|
||||||
{
|
{
|
||||||
|
|
@ -9,12 +12,29 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
{
|
{
|
||||||
public static IApplicationBuilder UseDispatcher(this IApplicationBuilder builder)
|
public static IApplicationBuilder UseDispatcher(this IApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
|
VerifyDispatcherIsRegistered(builder);
|
||||||
|
|
||||||
return builder.UseMiddleware<DispatcherMiddleware>();
|
return builder.UseMiddleware<DispatcherMiddleware>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IApplicationBuilder UseEndpoint(this IApplicationBuilder builder)
|
public static IApplicationBuilder UseEndpoint(this IApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
|
VerifyDispatcherIsRegistered(builder);
|
||||||
|
|
||||||
return builder.UseMiddleware<EndpointMiddleware>();
|
return builder.UseMiddleware<EndpointMiddleware>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void VerifyDispatcherIsRegistered(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
// Verify if AddDispatcher was done before calling UseDispatcher/UseEndpoint
|
||||||
|
// We use the DispatcherMarkerService to make sure if all the services were added.
|
||||||
|
if (app.ApplicationServices.GetService(typeof(DispatcherMarkerService)) == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(Resources.FormatUnableToFindServices(
|
||||||
|
nameof(IServiceCollection),
|
||||||
|
nameof(DispatcherServiceCollectionExtensions.AddDispatcher),
|
||||||
|
"ConfigureServices(...)"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Reflection;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
||||||
using Microsoft.AspNetCore.Routing.EndpointFinders;
|
using Microsoft.AspNetCore.Routing.EndpointFinders;
|
||||||
|
using Microsoft.AspNetCore.Routing.Internal;
|
||||||
using Microsoft.AspNetCore.Routing.Matchers;
|
using Microsoft.AspNetCore.Routing.Matchers;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
@ -34,6 +35,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
//
|
//
|
||||||
// Default matcher implementation
|
// Default matcher implementation
|
||||||
//
|
//
|
||||||
|
services.TryAddSingleton<MatchProcessorFactory, DefaultMatchProcessorFactory>();
|
||||||
services.TryAddSingleton<MatcherFactory, TreeMatcherFactory>();
|
services.TryAddSingleton<MatcherFactory, TreeMatcherFactory>();
|
||||||
|
|
||||||
// Link generation related services
|
// Link generation related services
|
||||||
|
|
@ -50,6 +52,8 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
services.TryAddEnumerable(
|
services.TryAddEnumerable(
|
||||||
ServiceDescriptor.Transient<IEndpointConstraintProvider, DefaultEndpointConstraintProvider>());
|
ServiceDescriptor.Transient<IEndpointConstraintProvider, DefaultEndpointConstraintProvider>());
|
||||||
|
|
||||||
|
services.TryAddSingleton(typeof(DispatcherMarkerService));
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
throw new ArgumentNullException(nameof(services));
|
throw new ArgumentNullException(nameof(services));
|
||||||
}
|
}
|
||||||
|
|
||||||
services.TryAddSingleton<MatchProcessorFactory, DefaultMatchProcessorFactory>();
|
|
||||||
services.TryAddTransient<IInlineConstraintResolver, DefaultInlineConstraintResolver>();
|
services.TryAddTransient<IInlineConstraintResolver, DefaultInlineConstraintResolver>();
|
||||||
services.TryAddSingleton<ObjectPool<UriBuildingContext>>(s =>
|
services.TryAddSingleton<ObjectPool<UriBuildingContext>>(s =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A marker class used to determine if all the dispatcher services were added
|
||||||
|
/// to the <see cref="IServiceCollection"/> before dispatcher is configured.
|
||||||
|
/// </summary>
|
||||||
|
internal class DispatcherMarkerService
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Routing.Internal
|
||||||
/// A marker class used to determine if all the routing services were added
|
/// A marker class used to determine if all the routing services were added
|
||||||
/// to the <see cref="IServiceCollection"/> before routing is configured.
|
/// to the <see cref="IServiceCollection"/> before routing is configured.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RoutingMarkerService
|
internal class RoutingMarkerService
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder.Internal;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Builder
|
||||||
|
{
|
||||||
|
public class DispatcherApplicationBuilderExtensions
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void UseDispatcher_ServicesNotRegistered_Throws()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var app = new ApplicationBuilder(Mock.Of<IServiceProvider>());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var ex = Assert.Throws<InvalidOperationException>(() => app.UseDispatcher());
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(
|
||||||
|
"Unable to find the required services. " +
|
||||||
|
"Please add all the required services by calling 'IServiceCollection.AddDispatcher' " +
|
||||||
|
"inside the call to 'ConfigureServices(...)' in the application startup code.",
|
||||||
|
ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void UseEndpoint_ServicesNotRegistered_Throws()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var app = new ApplicationBuilder(Mock.Of<IServiceProvider>());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var ex = Assert.Throws<InvalidOperationException>(() => app.UseEndpoint());
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(
|
||||||
|
"Unable to find the required services. " +
|
||||||
|
"Please add all the required services by calling 'IServiceCollection.AddDispatcher' " +
|
||||||
|
"inside the call to 'ConfigureServices(...)' in the application startup code.",
|
||||||
|
ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UseDispatcher_ServicesRegistered_SetsFeature()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = CreateServices();
|
||||||
|
|
||||||
|
var app = new ApplicationBuilder(services);
|
||||||
|
|
||||||
|
app.UseDispatcher();
|
||||||
|
|
||||||
|
var appFunc = app.Build();
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await appFunc(httpContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(httpContext.Features.Get<IEndpointFeature>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UseEndpoint_ServicesRegistered_SetsFeature()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = CreateServices();
|
||||||
|
|
||||||
|
var app = new ApplicationBuilder(services);
|
||||||
|
|
||||||
|
app.UseDispatcher();
|
||||||
|
app.UseEndpoint();
|
||||||
|
|
||||||
|
var appFunc = app.Build();
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await appFunc(httpContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(httpContext.Features.Get<IEndpointFeature>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private IServiceProvider CreateServices()
|
||||||
|
{
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddOptions();
|
||||||
|
services.AddDispatcher();
|
||||||
|
|
||||||
|
return services.BuildServiceProvider();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue