Use/EnsureRequestServices changes
- Split UseServices overloads into UseRequestServices and UseServices
- Add RequestServicesContainer class which contains the old
ContainerMiddleware logic and exposes a new
EnsureRequestServices(HttpContext) method which can be called to
populate RequestServices
- ConfigureServices now scans for Configure{Env}Services instead of
ConfigureServices{Env}
- Add OptionsServices as part of default HostingServices
This commit is contained in:
parent
ebe4948a3e
commit
6466d1061e
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNet.Security.DataProtection;
|
|||
using Microsoft.Framework.ConfigurationModel;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting
|
||||
{
|
||||
|
|
@ -41,6 +42,11 @@ namespace Microsoft.AspNet.Hosting
|
|||
|
||||
yield return describer.Scoped(typeof(IContextAccessor<>), typeof(ContextAccessor<>));
|
||||
|
||||
foreach (var service in OptionsServices.GetDefaultServices())
|
||||
{
|
||||
yield return service;
|
||||
}
|
||||
|
||||
foreach (var service in DataProtectionServices.GetDefaultServices())
|
||||
{
|
||||
yield return service;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace Microsoft.AspNet.Hosting
|
|||
// The application name is a "good enough" mechanism to identify this application
|
||||
// on the machine and to prevent subkeys from being shared across multiple applications
|
||||
// by default.
|
||||
serviceCollection.ConfigureOptions<DataProtectionOptions>(options =>
|
||||
serviceCollection.Configure<DataProtectionOptions>(options =>
|
||||
{
|
||||
options.ApplicationDiscriminator = appEnv.ApplicationName;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Builder;
|
||||
|
|
@ -27,16 +28,17 @@ namespace Microsoft.AspNet.Hosting.Startup
|
|||
|
||||
private MethodInfo FindMethod(Type startupType, string methodName, string environmentName, Type returnType = null, bool required = true)
|
||||
{
|
||||
var methodNameWithEnv = methodName + environmentName;
|
||||
var methodNameWithEnv = string.Format(CultureInfo.InvariantCulture, methodName, environmentName);
|
||||
var methodNameWithNoEnv = string.Format(CultureInfo.InvariantCulture, methodName, "");
|
||||
var methodInfo = startupType.GetTypeInfo().GetDeclaredMethod(methodNameWithEnv)
|
||||
?? startupType.GetTypeInfo().GetDeclaredMethod(methodName);
|
||||
?? startupType.GetTypeInfo().GetDeclaredMethod(methodNameWithNoEnv);
|
||||
if (methodInfo == null)
|
||||
{
|
||||
if (required)
|
||||
{
|
||||
throw new Exception(string.Format("TODO: {0} or {1} method not found",
|
||||
methodNameWithEnv,
|
||||
methodName));
|
||||
methodNameWithNoEnv));
|
||||
|
||||
}
|
||||
return null;
|
||||
|
|
@ -134,9 +136,9 @@ namespace Microsoft.AspNet.Hosting.Startup
|
|||
applicationName));
|
||||
}
|
||||
|
||||
var configureMethod = FindMethod(type, "Configure", environmentName, typeof(void), required: true);
|
||||
var configureMethod = FindMethod(type, "Configure{0}", environmentName, typeof(void), required: true);
|
||||
// TODO: accept IServiceProvider method as well?
|
||||
var servicesMethod = FindMethod(type, "ConfigureServices", environmentName, typeof(void), required: false);
|
||||
var servicesMethod = FindMethod(type, "Configure{0}Services", environmentName, typeof(void), required: false);
|
||||
|
||||
object instance = null;
|
||||
if (!configureMethod.IsStatic || (servicesMethod != null && !servicesMethod.IsStatic))
|
||||
|
|
|
|||
|
|
@ -31,33 +31,33 @@ namespace Microsoft.AspNet.Builder
|
|||
});
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UsePerRequestServices(this IApplicationBuilder builder)
|
||||
public static IApplicationBuilder UseRequestServices(this IApplicationBuilder builder)
|
||||
{
|
||||
return builder.UseMiddleware(typeof(ContainerMiddleware));
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UsePerRequestServices(this IApplicationBuilder builder, IServiceProvider applicationServices)
|
||||
public static IApplicationBuilder UseRequestServices(this IApplicationBuilder builder, IServiceProvider applicationServices)
|
||||
{
|
||||
builder.ApplicationServices = applicationServices;
|
||||
|
||||
return builder.UseMiddleware(typeof(ContainerMiddleware));
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UsePerRequestServices(this IApplicationBuilder builder, IEnumerable<IServiceDescriptor> applicationServices)
|
||||
public static IApplicationBuilder UseServices(this IApplicationBuilder builder, IEnumerable<IServiceDescriptor> applicationServices)
|
||||
{
|
||||
return builder.UsePerRequestServices(services => services.Add(applicationServices));
|
||||
return builder.UseServices(services => services.Add(applicationServices));
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UsePerRequestServices(this IApplicationBuilder builder, Action<ServiceCollection> configureServices)
|
||||
public static IApplicationBuilder UseServices(this IApplicationBuilder builder, Action<ServiceCollection> configureServices)
|
||||
{
|
||||
return builder.UsePerRequestServices(serviceCollection =>
|
||||
return builder.UseServices(serviceCollection =>
|
||||
{
|
||||
configureServices(serviceCollection);
|
||||
return serviceCollection.BuildServiceProvider(builder.ApplicationServices);
|
||||
});
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UsePerRequestServices(this IApplicationBuilder builder, Func<ServiceCollection, IServiceProvider> configureServices)
|
||||
public static IApplicationBuilder UseServices(this IApplicationBuilder builder, Func<ServiceCollection, IServiceProvider> configureServices)
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNet.RequestContainer
|
|||
_rootHttpContextAccessor.SetContextSource(AccessRootHttpContext, ExchangeRootHttpContext);
|
||||
}
|
||||
|
||||
private HttpContext AccessRootHttpContext()
|
||||
internal static HttpContext AccessRootHttpContext()
|
||||
{
|
||||
#if ASPNET50
|
||||
var handle = CallContext.LogicalGetData(LogicalDataKey) as ObjectHandle;
|
||||
|
|
@ -59,7 +59,7 @@ namespace Microsoft.AspNet.RequestContainer
|
|||
#endif
|
||||
}
|
||||
|
||||
private HttpContext ExchangeRootHttpContext(HttpContext httpContext)
|
||||
internal static HttpContext ExchangeRootHttpContext(HttpContext httpContext)
|
||||
{
|
||||
#if ASPNET50
|
||||
var prior = CallContext.LogicalGetData(LogicalDataKey) as ObjectHandle;
|
||||
|
|
@ -92,29 +92,9 @@ namespace Microsoft.AspNet.RequestContainer
|
|||
appHttpContextAccessor = priorApplicationServices.GetService<IContextAccessor<HttpContext>>();
|
||||
}
|
||||
|
||||
using (var scope = appServiceScopeFactory.CreateScope())
|
||||
using (var container = new RequestServicesContainer(httpContext, appServiceScopeFactory, appHttpContextAccessor, appServiceProvider))
|
||||
{
|
||||
var scopeServiceProvider = scope.ServiceProvider;
|
||||
var scopeHttpContextAccessor = scopeServiceProvider.GetService<IContextAccessor<HttpContext>>();
|
||||
|
||||
httpContext.ApplicationServices = appServiceProvider;
|
||||
httpContext.RequestServices = scopeServiceProvider;
|
||||
|
||||
var priorAppHttpContext = appHttpContextAccessor.SetValue(httpContext);
|
||||
var priorScopeHttpContext = scopeHttpContextAccessor.SetValue(httpContext);
|
||||
|
||||
try
|
||||
{
|
||||
await _next.Invoke(httpContext);
|
||||
}
|
||||
finally
|
||||
{
|
||||
scopeHttpContextAccessor.SetValue(priorScopeHttpContext);
|
||||
appHttpContextAccessor.SetValue(priorAppHttpContext);
|
||||
|
||||
httpContext.RequestServices = priorRequestServices;
|
||||
httpContext.ApplicationServices = priorApplicationServices;
|
||||
}
|
||||
await _next.Invoke(httpContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,142 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.RequestContainer
|
||||
{
|
||||
public class RequestServicesContainer : IDisposable
|
||||
{
|
||||
public RequestServicesContainer(
|
||||
HttpContext context,
|
||||
IServiceScopeFactory scopeFactory,
|
||||
IContextAccessor<HttpContext> appContextAccessor,
|
||||
IServiceProvider appServiceProvider)
|
||||
{
|
||||
if (scopeFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(scopeFactory));
|
||||
}
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
if (appContextAccessor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(appContextAccessor));
|
||||
}
|
||||
|
||||
AppContextAccessor = appContextAccessor;
|
||||
|
||||
Context = context;
|
||||
PriorAppServices = context.ApplicationServices;
|
||||
PriorRequestServices = context.RequestServices;
|
||||
|
||||
// Begin the scope
|
||||
Scope = scopeFactory.CreateScope();
|
||||
ScopeContextAccessor = Scope.ServiceProvider.GetService<IContextAccessor<HttpContext>>();
|
||||
|
||||
Context.ApplicationServices = appServiceProvider;
|
||||
Context.RequestServices = Scope.ServiceProvider;
|
||||
|
||||
PriorAppHttpContext = AppContextAccessor.SetValue(context);
|
||||
PriorScopeHttpContext = ScopeContextAccessor.SetValue(context);
|
||||
}
|
||||
|
||||
private HttpContext Context { get; set; }
|
||||
private IServiceProvider PriorAppServices { get; set; }
|
||||
private IServiceProvider PriorRequestServices { get; set; }
|
||||
private HttpContext PriorAppHttpContext { get; set; }
|
||||
private HttpContext PriorScopeHttpContext { get; set; }
|
||||
private IServiceScope Scope { get; set; }
|
||||
private IContextAccessor<HttpContext> ScopeContextAccessor { get; set; }
|
||||
private IContextAccessor<HttpContext> AppContextAccessor { get; set; }
|
||||
|
||||
// CONSIDER: this could be an extension method on HttpContext instead
|
||||
public static RequestServicesContainer EnsureRequestServices(HttpContext httpContext)
|
||||
{
|
||||
// All done if we already have a request services
|
||||
if (httpContext.RequestServices != null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (httpContext.ApplicationServices == null)
|
||||
{
|
||||
throw new InvalidOperationException("TODO: httpContext.ApplicationServices is null!");
|
||||
}
|
||||
|
||||
// Matches constructor of RequestContainer
|
||||
var rootServiceProvider = httpContext.ApplicationServices.GetService<IServiceProvider>();
|
||||
var rootHttpContextAccessor = httpContext.ApplicationServices.GetService<IContextAccessor<HttpContext>>();
|
||||
var rootServiceScopeFactory = httpContext.ApplicationServices.GetService<IServiceScopeFactory>();
|
||||
|
||||
rootHttpContextAccessor.SetContextSource(ContainerMiddleware.AccessRootHttpContext, ContainerMiddleware.ExchangeRootHttpContext);
|
||||
|
||||
// Pre Scope setup
|
||||
var priorApplicationServices = httpContext.ApplicationServices;
|
||||
var priorRequestServices = httpContext.RequestServices;
|
||||
|
||||
var appServiceProvider = rootServiceProvider;
|
||||
var appServiceScopeFactory = rootServiceScopeFactory;
|
||||
var appHttpContextAccessor = rootHttpContextAccessor;
|
||||
|
||||
if (priorApplicationServices != null &&
|
||||
priorApplicationServices != appServiceProvider)
|
||||
{
|
||||
appServiceProvider = priorApplicationServices;
|
||||
appServiceScopeFactory = priorApplicationServices.GetService<IServiceScopeFactory>();
|
||||
appHttpContextAccessor = priorApplicationServices.GetService<IContextAccessor<HttpContext>>();
|
||||
}
|
||||
|
||||
// Creates the scope and does the service swaps
|
||||
return new RequestServicesContainer(httpContext, appServiceScopeFactory, appHttpContextAccessor, appServiceProvider);
|
||||
}
|
||||
|
||||
#region IDisposable Support
|
||||
private bool disposedValue = false; // To detect redundant calls
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
ScopeContextAccessor.SetValue(PriorScopeHttpContext);
|
||||
AppContextAccessor.SetValue(PriorAppHttpContext);
|
||||
|
||||
Context.RequestServices = PriorRequestServices;
|
||||
Context.ApplicationServices = PriorAppServices;
|
||||
}
|
||||
|
||||
if (Scope != null)
|
||||
{
|
||||
Scope.Dispose();
|
||||
Scope = null;
|
||||
}
|
||||
|
||||
Context = null;
|
||||
PriorAppServices = null;
|
||||
PriorRequestServices = null;
|
||||
ScopeContextAccessor = null;
|
||||
AppContextAccessor = null;
|
||||
PriorAppHttpContext = null;
|
||||
PriorScopeHttpContext = null;
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
// This code added to correctly implement the disposable pattern.
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||
Dispose(true);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -7,5 +7,6 @@ namespace Microsoft.AspNet.Hosting.Fakes
|
|||
{
|
||||
public bool Configured { get; set; }
|
||||
public string Environment { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Fakes
|
||||
{
|
||||
public interface IFakeService { }
|
||||
public class FakeService : IFakeService { }
|
||||
}
|
||||
|
|
@ -14,37 +14,37 @@ namespace Microsoft.AspNet.Hosting.Fakes
|
|||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.ConfigureOptions<FakeOptions>(o => o.Configured = true);
|
||||
services.Configure<FakeOptions>(o => o.Configured = true);
|
||||
}
|
||||
|
||||
public void ConfigureServicesDev(IServiceCollection services)
|
||||
public void ConfigureDevServices(IServiceCollection services)
|
||||
{
|
||||
services.ConfigureOptions<FakeOptions>(o =>
|
||||
services.Configure<FakeOptions>(o =>
|
||||
{
|
||||
o.Configured = true;
|
||||
o.Environment = "Dev";
|
||||
});
|
||||
}
|
||||
|
||||
public void ConfigureServicesRetail(IServiceCollection services)
|
||||
public void ConfigureRetailServices(IServiceCollection services)
|
||||
{
|
||||
services.ConfigureOptions<FakeOptions>(o =>
|
||||
services.Configure<FakeOptions>(o =>
|
||||
{
|
||||
o.Configured = true;
|
||||
o.Environment = "Retail";
|
||||
});
|
||||
}
|
||||
|
||||
public static void ConfigureServicesStatic(IServiceCollection services)
|
||||
public static void ConfigureStaticServices(IServiceCollection services)
|
||||
{
|
||||
services.ConfigureOptions<FakeOptions>(o =>
|
||||
services.Configure<FakeOptions>(o =>
|
||||
{
|
||||
o.Configured = true;
|
||||
o.Environment = "Static";
|
||||
});
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder builder)
|
||||
public virtual void Configure(IApplicationBuilder builder)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Fakes
|
||||
{
|
||||
public class StartupBoom
|
||||
{
|
||||
public StartupBoom()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Fakes
|
||||
{
|
||||
public class StartupUseServices
|
||||
{
|
||||
public StartupUseServices()
|
||||
{
|
||||
}
|
||||
|
||||
public void ConfigureUseServicesServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<FakeOptions>(o => o.Configured = true);
|
||||
services.AddTransient<IFakeService, FakeService>();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder builder)
|
||||
{
|
||||
builder.UseServices(services =>
|
||||
{
|
||||
services.AddTransient<FakeService>();
|
||||
services.Configure<FakeOptions>(o => o.Message = "Configured");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<DevelopmentServerPort>29216</DevelopmentServerPort>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -53,14 +53,37 @@ namespace Microsoft.AspNet.Hosting
|
|||
|
||||
startup.Invoke(app);
|
||||
|
||||
var options = app.ApplicationServices.GetService<IOptionsAccessor<FakeOptions>>().Options;
|
||||
var options = app.ApplicationServices.GetService<IOptions<FakeOptions>>().Options;
|
||||
Assert.NotNull(options);
|
||||
Assert.True(options.Configured);
|
||||
Assert.Equal(environment, options.Environment);
|
||||
}
|
||||
|
||||
[Fact(Skip = "DataProtection registers default Options services; need to figure out what to do with this test.")]
|
||||
public void StartupClassDoesNotRegisterOptionsWithNoConfigureServices()
|
||||
[Fact]
|
||||
public void StartupClassWithConfigureServicesAndUseServicesAddsBothToServices()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.Add(HostingServices.GetDefaultServices());
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
var manager = services.GetService<IStartupManager>();
|
||||
|
||||
var startup = manager.LoadStartup("Microsoft.AspNet.Hosting.Tests", "UseServices");
|
||||
|
||||
var app = new ApplicationBuilder(services);
|
||||
|
||||
startup.Invoke(app);
|
||||
|
||||
Assert.NotNull(app.ApplicationServices.GetService<FakeService>());
|
||||
Assert.NotNull(app.ApplicationServices.GetService<IFakeService>());
|
||||
|
||||
var options = app.ApplicationServices.GetService<IOptions<FakeOptions>>().Options;
|
||||
Assert.NotNull(options);
|
||||
Assert.Equal("Configured", options.Message);
|
||||
Assert.False(options.Configured); // REVIEW: why doesn't the ConfigureServices ConfigureOptions get run?
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartupWithNoConfigureThrows()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.Add(HostingServices.GetDefaultServices());
|
||||
|
|
@ -68,14 +91,8 @@ namespace Microsoft.AspNet.Hosting
|
|||
var services = serviceCollection.BuildServiceProvider();
|
||||
var manager = services.GetService<IStartupManager>();
|
||||
|
||||
var startup = manager.LoadStartup("Microsoft.AspNet.Hosting.Tests", "NoServices");
|
||||
|
||||
var app = new ApplicationBuilder(services);
|
||||
|
||||
startup.Invoke(app);
|
||||
|
||||
var ex = Assert.Throws<Exception>(() => app.ApplicationServices.GetService<IOptionsAccessor<FakeOptions>>());
|
||||
Assert.True(ex.Message.Contains("No service for type 'Microsoft.Framework.OptionsModel.IOptionsAccessor"));
|
||||
var ex = Assert.Throws<Exception>(() => manager.LoadStartup("Microsoft.AspNet.Hosting.Tests", "Boom"));
|
||||
Assert.True(ex.Message.Contains("ConfigureBoom or Configure method not found"));
|
||||
}
|
||||
|
||||
public void ConfigurationMethodCalled(object instance)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||
using Xunit;
|
||||
using Microsoft.AspNet.PipelineCore;
|
||||
using Microsoft.AspNet.RequestContainer;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Tests
|
||||
{
|
||||
public class RequestServicesContainerFacts
|
||||
{
|
||||
[Fact]
|
||||
public void RequestServicesAvailableOnlyAfterRequestServices()
|
||||
{
|
||||
var baseServiceProvider = new ServiceCollection()
|
||||
.Add(HostingServices.GetDefaultServices())
|
||||
.BuildServiceProvider();
|
||||
var builder = new ApplicationBuilder(baseServiceProvider);
|
||||
|
||||
bool foundRequestServicesBefore = false;
|
||||
builder.Use(next => async c =>
|
||||
{
|
||||
foundRequestServicesBefore = c.RequestServices != null;
|
||||
await next.Invoke(c);
|
||||
});
|
||||
builder.UseRequestServices();
|
||||
bool foundRequestServicesAfter = false;
|
||||
builder.Use(next => async c =>
|
||||
{
|
||||
foundRequestServicesAfter = c.RequestServices != null;
|
||||
await next.Invoke(c);
|
||||
});
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
builder.Build().Invoke(context);
|
||||
Assert.False(foundRequestServicesBefore);
|
||||
Assert.True(foundRequestServicesAfter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureRequestServicesSetsRequestServices()
|
||||
{
|
||||
var baseServiceProvider = new ServiceCollection()
|
||||
.Add(HostingServices.GetDefaultServices())
|
||||
.BuildServiceProvider();
|
||||
var builder = new ApplicationBuilder(baseServiceProvider);
|
||||
|
||||
bool foundRequestServicesBefore = false;
|
||||
builder.Use(next => async c =>
|
||||
{
|
||||
foundRequestServicesBefore = c.RequestServices != null;
|
||||
await next.Invoke(c);
|
||||
});
|
||||
builder.Use(next => async c =>
|
||||
{
|
||||
using (var container = RequestServicesContainer.EnsureRequestServices(c))
|
||||
{
|
||||
await next.Invoke(c);
|
||||
}
|
||||
});
|
||||
bool foundRequestServicesAfter = false;
|
||||
builder.Use(next => async c =>
|
||||
{
|
||||
foundRequestServicesAfter = c.RequestServices != null;
|
||||
await next.Invoke(c);
|
||||
});
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
context.ApplicationServices = baseServiceProvider;
|
||||
builder.Build().Invoke(context);
|
||||
Assert.False(foundRequestServicesBefore);
|
||||
Assert.True(foundRequestServicesAfter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@ using Microsoft.Framework.DependencyInjection;
|
|||
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Xunit;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.PipelineCore;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Tests
|
||||
{
|
||||
|
|
@ -18,9 +20,9 @@ namespace Microsoft.AspNet.Hosting.Tests
|
|||
var baseServiceProvider = new ServiceCollection().BuildServiceProvider();
|
||||
var builder = new ApplicationBuilder(baseServiceProvider);
|
||||
|
||||
builder.UsePerRequestServices(serviceCollection => { });
|
||||
builder.UseServices(serviceCollection => { });
|
||||
|
||||
var optionsAccessor = builder.ApplicationServices.GetService<IOptionsAccessor<object>>();
|
||||
var optionsAccessor = builder.ApplicationServices.GetService<IOptions<object>>();
|
||||
Assert.NotNull(optionsAccessor);
|
||||
}
|
||||
|
||||
|
|
@ -32,14 +34,14 @@ namespace Microsoft.AspNet.Hosting.Tests
|
|||
var builder = new ApplicationBuilder(baseServiceProvider);
|
||||
IServiceProvider serviceProvider = null;
|
||||
|
||||
builder.UsePerRequestServices(serviceCollection =>
|
||||
builder.UseServices(serviceCollection =>
|
||||
{
|
||||
serviceProvider = serviceCollection.BuildServiceProvider(builder.ApplicationServices);
|
||||
return serviceProvider;
|
||||
});
|
||||
|
||||
Assert.Same(serviceProvider, builder.ApplicationServices);
|
||||
var optionsAccessor = builder.ApplicationServices.GetService<IOptionsAccessor<object>>();
|
||||
var optionsAccessor = builder.ApplicationServices.GetService<IOptions<object>>();
|
||||
Assert.NotNull(optionsAccessor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<DevelopmentServerPort>29215</DevelopmentServerPort>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
Loading…
Reference in New Issue