Rework hosting
- IStartupFilter support - Rework HostingEngine - AutoRequestScope by default via (IStartupFilter) - RIP RequestContainer
This commit is contained in:
parent
de44c3be99
commit
19b75b688a
15
Hosting.sln
15
Hosting.sln
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.22530.0
|
||||
VisualStudioVersion = 14.0.22710.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E0497F39-AFFB-4819-A116-E39E361915AB}"
|
||||
EndProject
|
||||
|
|
@ -15,8 +15,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Hosting",
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Hosting.Tests", "test\Microsoft.AspNet.Hosting.Tests\Microsoft.AspNet.Hosting.Tests.xproj", "{D4F18D58-52B1-435D-A012-10F2CDF158C4}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.RequestContainer", "src\Microsoft.AspNet.RequestContainer\Microsoft.AspNet.RequestContainer.xproj", "{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A66E3673-3976-4152-B902-2D0EC1428EA2}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
global.json = global.json
|
||||
|
|
@ -74,16 +72,6 @@ Global
|
|||
{D4F18D58-52B1-435D-A012-10F2CDF158C4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{D4F18D58-52B1-435D-A012-10F2CDF158C4}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{D4F18D58-52B1-435D-A012-10F2CDF158C4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BB780FBB-7842-4759-8DE7-96FA2E5571C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BB780FBB-7842-4759-8DE7-96FA2E5571C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BB780FBB-7842-4759-8DE7-96FA2E5571C1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -105,7 +93,6 @@ Global
|
|||
{1A415A3F-1081-45DB-809B-EE19CEA02DC0} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||
{3944F036-7E75-47E8-AA52-C4B89A64EC3A} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||
{D4F18D58-52B1-435D-A012-10F2CDF158C4} = {FEB39027-9158-4DE2-997F-7ADAEF8188D0}
|
||||
{374A5B0C-3E93-4A23-A4A0-EE2AB6DF7814} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||
{BB780FBB-7842-4759-8DE7-96FA2E5571C1} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace Microsoft.AspNet.Hosting
|
|||
{
|
||||
public interface IHostingEnvironment
|
||||
{
|
||||
string EnvironmentName { get; set; }
|
||||
string EnvironmentName { get; set; }
|
||||
|
||||
string WebRootPath { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
// 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.Framework.ConfigurationModel;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting
|
||||
{
|
||||
internal class ConfigureHostingEnvironment : IConfigureHostingEnvironment
|
||||
{
|
||||
private IConfiguration _config;
|
||||
private const string EnvironmentKey = "ASPNET_ENV";
|
||||
|
||||
public ConfigureHostingEnvironment(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public void Configure(IHostingEnvironment hostingEnv)
|
||||
{
|
||||
hostingEnv.EnvironmentName = _config?.Get(EnvironmentKey) ?? hostingEnv.EnvironmentName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,22 +4,29 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Hosting.Server;
|
||||
using Microsoft.AspNet.Hosting.Startup;
|
||||
using Microsoft.Framework.ConfigurationModel;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting
|
||||
{
|
||||
public class HostingContext
|
||||
{
|
||||
public IApplicationLifetime ApplicationLifetime { get; set; }
|
||||
public IConfiguration Configuration { get; set; }
|
||||
|
||||
public IApplicationBuilder Builder { get; set; }
|
||||
|
||||
public string ApplicationName { get; set; }
|
||||
public string WebRootPath { get; set; }
|
||||
public string EnvironmentName { get; set; }
|
||||
public Action<IApplicationBuilder> ApplicationStartup { get; set; }
|
||||
public StartupMethods StartupMethods { get; set; }
|
||||
public RequestDelegate ApplicationDelegate { get; set; }
|
||||
|
||||
public IServiceCollection Services { get; } = new ServiceCollection();
|
||||
|
||||
// Result of ConfigureServices
|
||||
public IServiceProvider ApplicationServices { get; set; }
|
||||
|
||||
public string ServerFactoryLocation { get; set; }
|
||||
public IServerFactory ServerFactory { get; set; }
|
||||
public IServerInformation Server { get; set; }
|
||||
|
|
|
|||
|
|
@ -9,51 +9,116 @@ using Microsoft.AspNet.Hosting.Builder;
|
|||
using Microsoft.AspNet.Hosting.Internal;
|
||||
using Microsoft.AspNet.Hosting.Server;
|
||||
using Microsoft.AspNet.Hosting.Startup;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Microsoft.Framework.Runtime.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting
|
||||
{
|
||||
public class HostingEngine : IHostingEngine
|
||||
public class HostingEngine
|
||||
{
|
||||
private readonly IServerLoader _serverManager;
|
||||
private readonly IStartupLoader _startupLoader;
|
||||
private readonly IApplicationBuilderFactory _builderFactory;
|
||||
private readonly IHttpContextFactory _httpContextFactory;
|
||||
private readonly IHttpContextAccessor _contextAccessor;
|
||||
private const string EnvironmentKey = "ASPNET_ENV";
|
||||
|
||||
public HostingEngine(
|
||||
IServerLoader serverManager,
|
||||
IStartupLoader startupLoader,
|
||||
IApplicationBuilderFactory builderFactory,
|
||||
IHttpContextFactory httpContextFactory,
|
||||
IHttpContextAccessor contextAccessor)
|
||||
private readonly IServiceProvider _fallbackServices;
|
||||
private readonly ApplicationLifetime _appLifetime;
|
||||
private readonly IApplicationEnvironment _applicationEnvironment;
|
||||
private readonly HostingEnvironment _hostingEnvironment;
|
||||
|
||||
private IServerLoader _serverLoader;
|
||||
private IApplicationBuilderFactory _builderFactory;
|
||||
|
||||
public HostingEngine() : this(fallbackServices: null) { }
|
||||
|
||||
public HostingEngine(IServiceProvider fallbackServices)
|
||||
{
|
||||
_serverManager = serverManager;
|
||||
_startupLoader = startupLoader;
|
||||
_builderFactory = builderFactory;
|
||||
_httpContextFactory = httpContextFactory;
|
||||
_contextAccessor = contextAccessor;
|
||||
_fallbackServices = fallbackServices ?? CallContextServiceLocator.Locator.ServiceProvider;
|
||||
_appLifetime = new ApplicationLifetime();
|
||||
_applicationEnvironment = _fallbackServices.GetRequiredService<IApplicationEnvironment>();
|
||||
_hostingEnvironment = new HostingEnvironment(_applicationEnvironment);
|
||||
_fallbackServices = new WrappingServiceProvider(_fallbackServices, _hostingEnvironment, _appLifetime);
|
||||
}
|
||||
|
||||
public IDisposable Start(HostingContext context)
|
||||
{
|
||||
EnsureContextDefaults(context);
|
||||
EnsureApplicationServices(context);
|
||||
EnsureBuilder(context);
|
||||
EnsureServerFactory(context);
|
||||
InitalizeServerFactory(context);
|
||||
EnsureApplicationDelegate(context);
|
||||
|
||||
var applicationLifetime = (ApplicationLifetime)context.ApplicationLifetime;
|
||||
var pipeline = new PipelineInstance(_httpContextFactory, context.ApplicationDelegate, _contextAccessor);
|
||||
var server = context.ServerFactory.Start(context.Server, pipeline.Invoke);
|
||||
var contextFactory = context.ApplicationServices.GetRequiredService<IHttpContextFactory>();
|
||||
var contextAccessor = context.ApplicationServices.GetRequiredService<IHttpContextAccessor>();
|
||||
var server = context.ServerFactory.Start(context.Server,
|
||||
features =>
|
||||
{
|
||||
var httpContext = contextFactory.CreateHttpContext(features);
|
||||
contextAccessor.HttpContext = httpContext;
|
||||
return context.ApplicationDelegate(httpContext);
|
||||
});
|
||||
|
||||
return new Disposable(() =>
|
||||
{
|
||||
applicationLifetime.NotifyStopping();
|
||||
_appLifetime.NotifyStopping();
|
||||
server.Dispose();
|
||||
pipeline.Dispose();
|
||||
applicationLifetime.NotifyStopped();
|
||||
_appLifetime.NotifyStopped();
|
||||
});
|
||||
}
|
||||
|
||||
private void EnsureContextDefaults(HostingContext context)
|
||||
{
|
||||
if (context.ApplicationName == null)
|
||||
{
|
||||
context.ApplicationName = _applicationEnvironment.ApplicationName;
|
||||
}
|
||||
|
||||
if (context.EnvironmentName == null)
|
||||
{
|
||||
context.EnvironmentName = context.Configuration?.Get(EnvironmentKey) ?? HostingEnvironment.DefaultEnvironmentName;
|
||||
}
|
||||
|
||||
_hostingEnvironment.EnvironmentName = context.EnvironmentName;
|
||||
|
||||
if (context.WebRootPath != null)
|
||||
{
|
||||
_hostingEnvironment.WebRootPath = context.WebRootPath;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureApplicationServices(HostingContext context)
|
||||
{
|
||||
if (context.ApplicationServices != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureStartupMethods(context);
|
||||
|
||||
context.ApplicationServices = context.StartupMethods.ConfigureServicesDelegate(CreateHostingServices(context));
|
||||
}
|
||||
|
||||
private void EnsureStartupMethods(HostingContext context)
|
||||
{
|
||||
if (context.StartupMethods != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var diagnosticMessages = new List<string>();
|
||||
context.StartupMethods = ApplicationStartup.LoadStartupMethods(
|
||||
_fallbackServices,
|
||||
context.ApplicationName,
|
||||
context.EnvironmentName,
|
||||
diagnosticMessages);
|
||||
|
||||
if (context.StartupMethods == null)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
diagnosticMessages.Aggregate("Failed to find an entry point for the web application.", (a, b) => a + "\r\n" + b),
|
||||
nameof(context));
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureBuilder(HostingContext context)
|
||||
{
|
||||
if (context.Builder != null)
|
||||
|
|
@ -61,7 +126,13 @@ namespace Microsoft.AspNet.Hosting
|
|||
return;
|
||||
}
|
||||
|
||||
if (_builderFactory == null)
|
||||
{
|
||||
_builderFactory = context.ApplicationServices.GetRequiredService<IApplicationBuilderFactory>();
|
||||
}
|
||||
|
||||
context.Builder = _builderFactory.CreateBuilder();
|
||||
context.Builder.ApplicationServices = context.ApplicationServices;
|
||||
}
|
||||
|
||||
private void EnsureServerFactory(HostingContext context)
|
||||
|
|
@ -71,7 +142,12 @@ namespace Microsoft.AspNet.Hosting
|
|||
return;
|
||||
}
|
||||
|
||||
context.ServerFactory = _serverManager.LoadServerFactory(context.ServerFactoryLocation);
|
||||
if (_serverLoader == null)
|
||||
{
|
||||
_serverLoader = context.ApplicationServices.GetRequiredService<IServerLoader>();
|
||||
}
|
||||
|
||||
context.ServerFactory = _serverLoader.LoadServerFactory(context.ServerFactoryLocation);
|
||||
}
|
||||
|
||||
private void InitalizeServerFactory(HostingContext context)
|
||||
|
|
@ -87,6 +163,32 @@ namespace Microsoft.AspNet.Hosting
|
|||
}
|
||||
}
|
||||
|
||||
private IServiceCollection CreateHostingServices(HostingContext context)
|
||||
{
|
||||
var services = Import(_fallbackServices);
|
||||
|
||||
services.TryAdd(ServiceDescriptor.Transient<IServerLoader, ServerLoader>());
|
||||
|
||||
services.TryAdd(ServiceDescriptor.Transient<IApplicationBuilderFactory, ApplicationBuilderFactory>());
|
||||
services.TryAdd(ServiceDescriptor.Transient<IHttpContextFactory, HttpContextFactory>());
|
||||
|
||||
// TODO: Do we expect this to be provide by the runtime eventually?
|
||||
services.AddLogging();
|
||||
services.TryAdd(ServiceDescriptor.Singleton<IHttpContextAccessor, HttpContextAccessor>());
|
||||
|
||||
// Apply user services
|
||||
services.Add(context.Services);
|
||||
|
||||
// Jamming in app lifetime and hosting env since these must not be replaceable
|
||||
services.AddInstance<IApplicationLifetime>(_appLifetime);
|
||||
services.AddInstance<IHostingEnvironment>(_hostingEnvironment);
|
||||
|
||||
// Conjure up a RequestServices
|
||||
services.AddTransient<IStartupFilter, AutoRequestServicesStartupFilter>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
private void EnsureApplicationDelegate(HostingContext context)
|
||||
{
|
||||
if (context.ApplicationDelegate != null)
|
||||
|
|
@ -94,30 +196,59 @@ namespace Microsoft.AspNet.Hosting
|
|||
return;
|
||||
}
|
||||
|
||||
EnsureApplicationStartup(context);
|
||||
// REVIEW: should we call EnsureApplicationServices?
|
||||
var startupFilters = context.ApplicationServices.GetService<IEnumerable<IStartupFilter>>();
|
||||
var configure = context.StartupMethods.ConfigureDelegate;
|
||||
foreach (var filter in startupFilters)
|
||||
{
|
||||
configure = filter.Configure(context.Builder, configure);
|
||||
}
|
||||
|
||||
configure(context.Builder);
|
||||
|
||||
context.ApplicationStartup.Invoke(context.Builder);
|
||||
context.ApplicationDelegate = context.Builder.Build();
|
||||
}
|
||||
|
||||
private void EnsureApplicationStartup(HostingContext context)
|
||||
private static IServiceCollection Import(IServiceProvider fallbackProvider)
|
||||
{
|
||||
if (context.ApplicationStartup != null)
|
||||
var services = new ServiceCollection();
|
||||
var manifest = fallbackProvider.GetRequiredService<IServiceManifest>();
|
||||
foreach (var service in manifest.Services)
|
||||
{
|
||||
return;
|
||||
services.AddTransient(service, sp => fallbackProvider.GetService(service));
|
||||
}
|
||||
|
||||
var diagnosticMessages = new List<string>();
|
||||
context.ApplicationStartup = _startupLoader.LoadStartup(
|
||||
context.ApplicationName,
|
||||
context.EnvironmentName,
|
||||
diagnosticMessages);
|
||||
return services;
|
||||
}
|
||||
|
||||
if (context.ApplicationStartup == null)
|
||||
private class WrappingServiceProvider : IServiceProvider
|
||||
{
|
||||
private readonly IServiceProvider _sp;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly IApplicationLifetime _applicationLifetime;
|
||||
|
||||
public WrappingServiceProvider(IServiceProvider sp,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IApplicationLifetime applicationLifetime)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
diagnosticMessages.Aggregate("Failed to find an entry point for the web application.", (a, b) => a + "\r\n" + b),
|
||||
nameof(context));
|
||||
_sp = sp;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_applicationLifetime = applicationLifetime;
|
||||
}
|
||||
|
||||
public object GetService(Type serviceType)
|
||||
{
|
||||
if (serviceType == typeof(IHostingEnvironment))
|
||||
{
|
||||
return _hostingEnvironment;
|
||||
}
|
||||
|
||||
if (serviceType == typeof(IApplicationLifetime))
|
||||
{
|
||||
return _applicationLifetime;
|
||||
}
|
||||
|
||||
return _sp.GetService(serviceType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,22 +10,18 @@ namespace Microsoft.AspNet.Hosting
|
|||
{
|
||||
public class HostingEnvironment : IHostingEnvironment
|
||||
{
|
||||
private const string DefaultEnvironmentName = "Development";
|
||||
internal const string DefaultEnvironmentName = "Development";
|
||||
|
||||
public HostingEnvironment(IApplicationEnvironment appEnvironment, IEnumerable<IConfigureHostingEnvironment> configures)
|
||||
public HostingEnvironment(IApplicationEnvironment appEnvironment)
|
||||
{
|
||||
EnvironmentName = DefaultEnvironmentName;
|
||||
WebRootPath = HostingUtilities.GetWebRoot(appEnvironment.ApplicationBasePath);
|
||||
WebRootFileProvider = new PhysicalFileProvider(WebRootPath);
|
||||
foreach (var configure in configures)
|
||||
{
|
||||
configure.Configure(this);
|
||||
}
|
||||
}
|
||||
|
||||
public string EnvironmentName { get; set; }
|
||||
|
||||
public string WebRootPath { get; private set; }
|
||||
public string WebRootPath { get; set; }
|
||||
|
||||
public IFileProvider WebRootFileProvider { get; private set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,89 +0,0 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Framework.ConfigurationModel;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Microsoft.Framework.Runtime.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting
|
||||
{
|
||||
public static class HostingServices
|
||||
{
|
||||
private static IServiceCollection Import(IServiceProvider fallbackProvider, Action<IServiceCollection> configureHostServices)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
var manifest = fallbackProvider.GetRequiredService<IServiceManifest>();
|
||||
foreach (var service in manifest.Services)
|
||||
{
|
||||
services.AddTransient(service, sp => fallbackProvider.GetService(service));
|
||||
}
|
||||
|
||||
if (configureHostServices != null)
|
||||
{
|
||||
configureHostServices(services);
|
||||
}
|
||||
|
||||
services.AddSingleton<IServiceManifest>(sp => new HostingManifest(services));
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection Create()
|
||||
{
|
||||
return Create(CallContextServiceLocator.Locator.ServiceProvider, configureHostServices: null, configuration: null);
|
||||
}
|
||||
|
||||
public static IServiceCollection Create(IServiceProvider fallbackServices)
|
||||
{
|
||||
return Create(fallbackServices, configureHostServices: null, configuration: null);
|
||||
}
|
||||
|
||||
public static IServiceCollection Create(Action<IServiceCollection> configureHostServices)
|
||||
{
|
||||
return Create(CallContextServiceLocator.Locator.ServiceProvider, configureHostServices, configuration: null);
|
||||
}
|
||||
|
||||
public static IServiceCollection Create(IServiceProvider fallbackServices, Action<IServiceCollection> configureHostServices)
|
||||
{
|
||||
return Create(fallbackServices, configureHostServices, configuration: null);
|
||||
}
|
||||
|
||||
public static IServiceCollection Create(Action<IServiceCollection> configureHostServices, IConfiguration configuration)
|
||||
{
|
||||
return Create(CallContextServiceLocator.Locator.ServiceProvider, configureHostServices, configuration);
|
||||
}
|
||||
|
||||
public static IServiceCollection Create(IServiceProvider fallbackServices, IConfiguration configuration)
|
||||
{
|
||||
return Create(CallContextServiceLocator.Locator.ServiceProvider, configureHostServices: null, configuration: configuration);
|
||||
}
|
||||
|
||||
public static IServiceCollection Create(IServiceProvider fallbackServices, Action<IServiceCollection> configureHostServices, IConfiguration configuration)
|
||||
{
|
||||
var services = Import(fallbackServices, configureHostServices);
|
||||
services.AddHosting(configuration);
|
||||
return services;
|
||||
}
|
||||
|
||||
// Manifest exposes the fallback manifest in addition to ITypeActivator, IHostingEnvironment, and ILoggerFactory
|
||||
private class HostingManifest : IServiceManifest
|
||||
{
|
||||
public HostingManifest(IServiceCollection hostServices)
|
||||
{
|
||||
Services = new Type[] {
|
||||
typeof(IHostingEnvironment),
|
||||
typeof(ILoggerFactory),
|
||||
typeof(IHttpContextAccessor),
|
||||
typeof(IApplicationLifetime)
|
||||
}.Concat(hostServices.Select(s => s.ServiceType)).Distinct();
|
||||
}
|
||||
|
||||
public IEnumerable<Type> Services { get; private set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
// 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.Hosting;
|
||||
using Microsoft.AspNet.Hosting.Builder;
|
||||
using Microsoft.AspNet.Hosting.Server;
|
||||
using Microsoft.AspNet.Hosting.Startup;
|
||||
using Microsoft.Framework.ConfigurationModel;
|
||||
|
||||
namespace Microsoft.Framework.DependencyInjection
|
||||
{
|
||||
public static class HostingServicesExtensions
|
||||
{
|
||||
public static IServiceCollection AddHosting(this IServiceCollection services)
|
||||
{
|
||||
return services.AddHosting(configuration: null);
|
||||
}
|
||||
|
||||
public static IServiceCollection AddHosting(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.TryAdd(ServiceDescriptor.Transient<IHostingEngine, HostingEngine>());
|
||||
services.TryAdd(ServiceDescriptor.Transient<IServerLoader, ServerLoader>());
|
||||
|
||||
services.TryAdd(ServiceDescriptor.Transient<IStartupLoader, StartupLoader>());
|
||||
|
||||
services.TryAdd(ServiceDescriptor.Transient<IApplicationBuilderFactory, ApplicationBuilderFactory>());
|
||||
services.TryAdd(ServiceDescriptor.Transient<IHttpContextFactory, HttpContextFactory>());
|
||||
|
||||
services.TryAdd(ServiceDescriptor.Instance<IApplicationLifetime>(new ApplicationLifetime()));
|
||||
|
||||
// TODO: Do we expect this to be provide by the runtime eventually?
|
||||
services.AddLogging();
|
||||
services.TryAdd(ServiceDescriptor.Singleton<IHostingEnvironment, HostingEnvironment>());
|
||||
services.TryAdd(ServiceDescriptor.Singleton<IHttpContextAccessor, HttpContextAccessor>());
|
||||
|
||||
// REVIEW: don't try add because we pull out IEnumerable<IConfigureHostingEnvironment>?
|
||||
services.AddInstance<IConfigureHostingEnvironment>(new ConfigureHostingEnvironment(configuration));
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting
|
||||
{
|
||||
public interface IHostingEngine
|
||||
{
|
||||
IDisposable Start(HostingContext context);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// 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.Builder;
|
||||
using Microsoft.AspNet.Hosting.Startup;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Internal
|
||||
{
|
||||
public class AutoRequestServicesStartupFilter : IStartupFilter
|
||||
{
|
||||
public Action<IApplicationBuilder> Configure(IApplicationBuilder app, Action<IApplicationBuilder> next)
|
||||
{
|
||||
return builder =>
|
||||
{
|
||||
app.UseMiddleware<RequestServicesContainerMiddleware>();
|
||||
next(builder);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// 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 System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.FeatureModel;
|
||||
using Microsoft.AspNet.Hosting.Builder;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Internal
|
||||
{
|
||||
public class PipelineInstance : IDisposable
|
||||
{
|
||||
private readonly IHttpContextFactory _httpContextFactory;
|
||||
private readonly RequestDelegate _requestDelegate;
|
||||
private readonly IHttpContextAccessor _contextAccessor;
|
||||
|
||||
public PipelineInstance(IHttpContextFactory httpContextFactory, RequestDelegate requestDelegate, IHttpContextAccessor contextAccessor)
|
||||
{
|
||||
_httpContextFactory = httpContextFactory;
|
||||
_requestDelegate = requestDelegate;
|
||||
_contextAccessor = contextAccessor;
|
||||
}
|
||||
|
||||
public Task Invoke(IFeatureCollection featureCollection)
|
||||
{
|
||||
var httpContext = _httpContextFactory.CreateHttpContext(featureCollection);
|
||||
_contextAccessor.HttpContext = httpContext;
|
||||
return _requestDelegate(httpContext);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// TODO: application notification of disposal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ using System;
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.RequestContainer
|
||||
namespace Microsoft.AspNet.Hosting.Internal
|
||||
{
|
||||
public class RequestServicesContainer : IDisposable
|
||||
{
|
||||
|
|
@ -6,14 +6,14 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
|
||||
namespace Microsoft.AspNet.RequestContainer
|
||||
namespace Microsoft.AspNet.Hosting.Internal
|
||||
{
|
||||
public class ContainerMiddleware
|
||||
public class RequestServicesContainerMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public ContainerMiddleware(RequestDelegate next, IServiceProvider services)
|
||||
public RequestServicesContainerMiddleware(RequestDelegate next, IServiceProvider services)
|
||||
{
|
||||
_services = services;
|
||||
_next = next;
|
||||
|
|
@ -21,11 +21,6 @@ namespace Microsoft.AspNet.RequestContainer
|
|||
|
||||
public async Task Invoke(HttpContext httpContext)
|
||||
{
|
||||
if (httpContext.RequestServices != null)
|
||||
{
|
||||
throw new Exception("TODO: nested request container scope? this is probably a mistake on your part?");
|
||||
}
|
||||
|
||||
using (var container = RequestServicesContainer.EnsureRequestServices(httpContext, _services))
|
||||
{
|
||||
await _next.Invoke(httpContext);
|
||||
|
|
@ -33,29 +33,19 @@ namespace Microsoft.AspNet.Hosting
|
|||
config.AddEnvironmentVariables();
|
||||
config.AddCommandLine(args);
|
||||
|
||||
var services = HostingServices.Create(_serviceProvider, config)
|
||||
.BuildServiceProvider();
|
||||
|
||||
var appEnv = services.GetRequiredService<IApplicationEnvironment>();
|
||||
var hostingEnv = services.GetRequiredService<IHostingEnvironment>();
|
||||
var applicationLifetime = services.GetRequiredService<IApplicationLifetime>();
|
||||
|
||||
var context = new HostingContext()
|
||||
{
|
||||
ApplicationLifetime = applicationLifetime,
|
||||
Configuration = config,
|
||||
ServerFactoryLocation = config.Get("server"), // TODO: Key names
|
||||
ApplicationName = config.Get("app") // TODO: Key names
|
||||
?? appEnv.ApplicationName,
|
||||
EnvironmentName = hostingEnv.EnvironmentName,
|
||||
ServerFactoryLocation = config.Get("server"),
|
||||
ApplicationName = config.Get("app")
|
||||
};
|
||||
|
||||
var engine = services.GetRequiredService<IHostingEngine>();
|
||||
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
|
||||
var appShutdownService = _serviceProvider.GetRequiredService<IApplicationShutdown>();
|
||||
var shutdownHandle = new ManualResetEvent(false);
|
||||
|
||||
var engine = new HostingEngine(_serviceProvider);
|
||||
|
||||
var serverShutdown = engine.Start(context);
|
||||
var loggerFactory = context.ApplicationServices.GetRequiredService<ILoggerFactory>();
|
||||
var appShutdownService = context.ApplicationServices.GetRequiredService<IApplicationShutdown>();
|
||||
var shutdownHandle = new ManualResetEvent(false);
|
||||
|
||||
appShutdownService.ShutdownRequested.Register(() =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Startup
|
||||
{
|
||||
public static class ApplicationStartup
|
||||
{
|
||||
internal static ConfigureServicesDelegate DefaultBuildServiceProvider = s => s.BuildServiceProvider();
|
||||
|
||||
public static StartupMethods LoadStartupMethods(
|
||||
IServiceProvider services,
|
||||
string applicationName,
|
||||
string environmentName,
|
||||
IList<string> diagnosticMessages)
|
||||
{
|
||||
if (string.IsNullOrEmpty(applicationName))
|
||||
{
|
||||
throw new ArgumentException("Value cannot be null or empty.", "applicationName");
|
||||
}
|
||||
|
||||
var assembly = Assembly.Load(new AssemblyName(applicationName));
|
||||
if (assembly == null)
|
||||
{
|
||||
throw new InvalidOperationException(String.Format("The assembly '{0}' failed to load.", applicationName));
|
||||
}
|
||||
|
||||
var startupNameWithEnv = "Startup" + environmentName;
|
||||
var startupNameWithoutEnv = "Startup";
|
||||
|
||||
// Check the most likely places first
|
||||
var type =
|
||||
assembly.GetType(startupNameWithEnv) ??
|
||||
assembly.GetType(applicationName + "." + startupNameWithEnv) ??
|
||||
assembly.GetType(startupNameWithoutEnv) ??
|
||||
assembly.GetType(applicationName + "." + startupNameWithoutEnv);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
// Full scan
|
||||
var definedTypes = assembly.DefinedTypes.ToList();
|
||||
|
||||
var startupType1 = definedTypes.Where(info => info.Name.Equals(startupNameWithEnv, StringComparison.Ordinal));
|
||||
var startupType2 = definedTypes.Where(info => info.Name.Equals(startupNameWithoutEnv, StringComparison.Ordinal));
|
||||
|
||||
var typeInfo = startupType1.Concat(startupType2).FirstOrDefault();
|
||||
if (typeInfo != null)
|
||||
{
|
||||
type = typeInfo.AsType();
|
||||
}
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
throw new InvalidOperationException(String.Format("A type named '{0}' or '{1}' could not be found in assembly '{2}'.",
|
||||
startupNameWithEnv,
|
||||
startupNameWithoutEnv,
|
||||
applicationName));
|
||||
}
|
||||
|
||||
var configureMethod = FindConfigureDelegate(type, environmentName);
|
||||
var servicesMethod = FindConfigureServicesDelegate(type, environmentName);
|
||||
|
||||
object instance = null;
|
||||
if (!configureMethod.MethodInfo.IsStatic || (servicesMethod != null && !servicesMethod.MethodInfo.IsStatic))
|
||||
{
|
||||
instance = ActivatorUtilities.GetServiceOrCreateInstance(services, type);
|
||||
}
|
||||
|
||||
return new StartupMethods(configureMethod.Build(instance), servicesMethod?.Build(instance));
|
||||
}
|
||||
|
||||
|
||||
public static ConfigureBuilder FindConfigureDelegate(Type startupType, string environmentName)
|
||||
{
|
||||
var configureMethod = FindMethod(startupType, "Configure{0}", environmentName, typeof(void), required: true);
|
||||
return new ConfigureBuilder(configureMethod);
|
||||
}
|
||||
|
||||
public static ConfigureServicesBuilder FindConfigureServicesDelegate(Type startupType, string environmentName)
|
||||
{
|
||||
var servicesMethod = FindMethod(startupType, "Configure{0}Services", environmentName, typeof(IServiceProvider), required: false)
|
||||
?? FindMethod(startupType, "Configure{0}Services", environmentName, typeof(void), required: false);
|
||||
return servicesMethod == null ? null : new ConfigureServicesBuilder(servicesMethod);
|
||||
}
|
||||
|
||||
private static MethodInfo FindMethod(Type startupType, string methodName, string environmentName, Type returnType = null, bool required = true)
|
||||
{
|
||||
var methodNameWithEnv = string.Format(CultureInfo.InvariantCulture, methodName, environmentName);
|
||||
var methodNameWithNoEnv = string.Format(CultureInfo.InvariantCulture, methodName, "");
|
||||
var methodInfo = startupType.GetMethod(methodNameWithEnv, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
?? startupType.GetMethod(methodNameWithNoEnv, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
|
||||
if (methodInfo == null)
|
||||
{
|
||||
if (required)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("A method named '{0}' or '{1}' in the type '{2}' could not be found.",
|
||||
methodNameWithEnv,
|
||||
methodNameWithNoEnv,
|
||||
startupType.FullName));
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (returnType != null && methodInfo.ReturnType != returnType)
|
||||
{
|
||||
if (required)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("The '{0}' method in the type '{1}' must have a return type of '{2}'.",
|
||||
methodInfo.Name,
|
||||
startupType.FullName,
|
||||
returnType.Name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return methodInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// 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 System.Reflection;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Startup
|
||||
{
|
||||
// TODO: replace all Action<IApplicationBuilder> eventually with this
|
||||
public delegate void ConfigureDelegate(IApplicationBuilder builder);
|
||||
|
||||
public class ConfigureBuilder
|
||||
{
|
||||
public ConfigureBuilder(MethodInfo configure)
|
||||
{
|
||||
MethodInfo = configure;
|
||||
}
|
||||
|
||||
public MethodInfo MethodInfo { get; }
|
||||
|
||||
public Action<IApplicationBuilder> Build(object instance)
|
||||
{
|
||||
return builder => Invoke(instance, builder);
|
||||
}
|
||||
|
||||
private void Invoke(object instance, IApplicationBuilder builder)
|
||||
{
|
||||
var serviceProvider = builder.ApplicationServices;
|
||||
var parameterInfos = MethodInfo.GetParameters();
|
||||
var parameters = new object[parameterInfos.Length];
|
||||
for (var index = 0; index != parameterInfos.Length; ++index)
|
||||
{
|
||||
var parameterInfo = parameterInfos[index];
|
||||
if (parameterInfo.ParameterType == typeof(IApplicationBuilder))
|
||||
{
|
||||
parameters[index] = builder;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
parameters[index] = serviceProvider.GetRequiredService(parameterInfo.ParameterType);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new Exception(string.Format(
|
||||
"Could not resolve a service of type '{0}' for the parameter '{1}' of method '{2}' on type '{3}'.",
|
||||
parameterInfo.ParameterType.FullName,
|
||||
parameterInfo.Name,
|
||||
MethodInfo.Name,
|
||||
MethodInfo.DeclaringType.FullName));
|
||||
}
|
||||
}
|
||||
}
|
||||
MethodInfo.Invoke(instance, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// 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 System.Reflection;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Startup
|
||||
{
|
||||
public delegate IServiceProvider ConfigureServicesDelegate(IServiceCollection services);
|
||||
|
||||
public class ConfigureServicesBuilder
|
||||
{
|
||||
public ConfigureServicesBuilder(MethodInfo configureServices)
|
||||
{
|
||||
MethodInfo = configureServices;
|
||||
}
|
||||
|
||||
public MethodInfo MethodInfo { get; }
|
||||
|
||||
public ConfigureServicesDelegate Build(object instance)
|
||||
{
|
||||
return services => Invoke(instance, services);
|
||||
}
|
||||
|
||||
private IServiceProvider Invoke(object instance, IServiceCollection exportServices)
|
||||
{
|
||||
var parameterInfos = MethodInfo.GetParameters();
|
||||
var parameters = new object[parameterInfos.Length];
|
||||
for (var index = 0; index != parameterInfos.Length; ++index)
|
||||
{
|
||||
var parameterInfo = parameterInfos[index];
|
||||
if (exportServices != null && parameterInfo.ParameterType == typeof(IServiceCollection))
|
||||
{
|
||||
parameters[index] = exportServices;
|
||||
}
|
||||
}
|
||||
|
||||
// REVIEW: We null ref if exportServices is null, cuz it should not be null
|
||||
return MethodInfo.Invoke(instance, parameters) as IServiceProvider ?? exportServices.BuildServiceProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,16 +2,13 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Builder;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Startup
|
||||
{
|
||||
public interface IStartupLoader
|
||||
public interface IStartupFilter
|
||||
{
|
||||
Action<IApplicationBuilder> LoadStartup(
|
||||
string applicationName,
|
||||
string environmentName,
|
||||
IList<string> diagnosticMessages);
|
||||
// TODO: replace with ConfigureDelegate?
|
||||
Action<IApplicationBuilder> Configure(IApplicationBuilder app, Action<IApplicationBuilder> next);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Startup
|
||||
{
|
||||
public class StartupLoader : IStartupLoader
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public StartupLoader(IServiceProvider services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
private MethodInfo FindMethod(Type startupType, string methodName, string environmentName, Type returnType = null, bool required = true)
|
||||
{
|
||||
var methodNameWithEnv = string.Format(CultureInfo.InvariantCulture, methodName, environmentName);
|
||||
var methodNameWithNoEnv = string.Format(CultureInfo.InvariantCulture, methodName, "");
|
||||
var methodInfo = startupType.GetMethod(methodNameWithEnv, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
?? startupType.GetMethod(methodNameWithNoEnv, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
|
||||
if (methodInfo == null)
|
||||
{
|
||||
if (required)
|
||||
{
|
||||
throw new Exception(string.Format("A method named '{0}' or '{1}' in the type '{2}' could not be found.",
|
||||
methodNameWithEnv,
|
||||
methodNameWithNoEnv,
|
||||
startupType.FullName));
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (returnType != null && methodInfo.ReturnType != returnType)
|
||||
{
|
||||
if (required)
|
||||
{
|
||||
throw new Exception(string.Format("The '{0}' method in the type '{1}' must have a return type of '{2}'.",
|
||||
methodInfo.Name,
|
||||
startupType.FullName,
|
||||
returnType.Name));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return methodInfo;
|
||||
}
|
||||
|
||||
private object Invoke(MethodInfo methodInfo, object instance, IApplicationBuilder builder, IServiceCollection services = null)
|
||||
{
|
||||
var serviceProvider = builder.ApplicationServices ?? _services;
|
||||
var parameterInfos = methodInfo.GetParameters();
|
||||
var parameters = new object[parameterInfos.Length];
|
||||
for (var index = 0; index != parameterInfos.Length; ++index)
|
||||
{
|
||||
var parameterInfo = parameterInfos[index];
|
||||
if (parameterInfo.ParameterType == typeof(IApplicationBuilder))
|
||||
{
|
||||
parameters[index] = builder;
|
||||
}
|
||||
else if (services != null && parameterInfo.ParameterType == typeof(IServiceCollection))
|
||||
{
|
||||
parameters[index] = services;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
parameters[index] = serviceProvider.GetRequiredService(parameterInfo.ParameterType);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new Exception(string.Format(
|
||||
"Could not resolve a service of type '{0}' for the parameter '{1}' of method '{2}' on type '{3}'.",
|
||||
parameterInfo.ParameterType.FullName,
|
||||
parameterInfo.Name,
|
||||
methodInfo.Name,
|
||||
methodInfo.DeclaringType.FullName));
|
||||
}
|
||||
}
|
||||
}
|
||||
return methodInfo.Invoke(instance, parameters);
|
||||
}
|
||||
|
||||
public Action<IApplicationBuilder> LoadStartup(
|
||||
string applicationName,
|
||||
string environmentName,
|
||||
IList<string> diagnosticMessages)
|
||||
{
|
||||
if (string.IsNullOrEmpty(applicationName))
|
||||
{
|
||||
throw new ArgumentException("Value cannot be null or empty.", "applicationName");
|
||||
}
|
||||
|
||||
var assembly = Assembly.Load(new AssemblyName(applicationName));
|
||||
if (assembly == null)
|
||||
{
|
||||
throw new Exception(String.Format("The assembly '{0}' failed to load.", applicationName));
|
||||
}
|
||||
|
||||
var startupNameWithEnv = "Startup" + environmentName;
|
||||
var startupNameWithoutEnv = "Startup";
|
||||
|
||||
// Check the most likely places first
|
||||
var type =
|
||||
assembly.GetType(startupNameWithEnv) ??
|
||||
assembly.GetType(applicationName + "." + startupNameWithEnv) ??
|
||||
assembly.GetType(startupNameWithoutEnv) ??
|
||||
assembly.GetType(applicationName + "." + startupNameWithoutEnv);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
// Full scan
|
||||
var definedTypes = assembly.DefinedTypes.ToList();
|
||||
|
||||
var startupType1 = definedTypes.Where(info => info.Name.Equals(startupNameWithEnv, StringComparison.Ordinal));
|
||||
var startupType2 = definedTypes.Where(info => info.Name.Equals(startupNameWithoutEnv, StringComparison.Ordinal));
|
||||
|
||||
var typeInfo = startupType1.Concat(startupType2).FirstOrDefault();
|
||||
if (typeInfo != null)
|
||||
{
|
||||
type = typeInfo.AsType();
|
||||
}
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
throw new Exception(String.Format("A type named '{0}' or '{1}' could not be found in assembly '{2}'.",
|
||||
startupNameWithEnv,
|
||||
startupNameWithoutEnv,
|
||||
applicationName));
|
||||
}
|
||||
|
||||
var configureMethod = FindMethod(type, "Configure{0}", environmentName, typeof(void), required: true);
|
||||
var servicesMethod = FindMethod(type, "Configure{0}Services", environmentName, typeof(IServiceProvider), required: false)
|
||||
?? FindMethod(type, "Configure{0}Services", environmentName, typeof(void), required: false);
|
||||
|
||||
object instance = null;
|
||||
if (!configureMethod.IsStatic || (servicesMethod != null && !servicesMethod.IsStatic))
|
||||
{
|
||||
instance = ActivatorUtilities.GetServiceOrCreateInstance(_services, type);
|
||||
}
|
||||
return builder =>
|
||||
{
|
||||
if (servicesMethod != null)
|
||||
{
|
||||
var services = HostingServices.Create(builder.ApplicationServices);
|
||||
if (servicesMethod.ReturnType == typeof(IServiceProvider))
|
||||
{
|
||||
// IServiceProvider ConfigureServices(IServiceCollection)
|
||||
builder.ApplicationServices = (Invoke(servicesMethod, instance, builder, services) as IServiceProvider)
|
||||
?? builder.ApplicationServices;
|
||||
}
|
||||
else
|
||||
{
|
||||
// void ConfigureServices(IServiceCollection)
|
||||
Invoke(servicesMethod, instance, builder, services);
|
||||
if (builder != null)
|
||||
{
|
||||
builder.ApplicationServices = services.BuildServiceProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
Invoke(configureMethod, instance, builder);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// 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.Builder;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Startup
|
||||
{
|
||||
public class StartupMethods
|
||||
{
|
||||
// TODO: switch to ConfigureDelegate eventually
|
||||
public StartupMethods(Action<IApplicationBuilder> configure, ConfigureServicesDelegate configureServices)
|
||||
{
|
||||
ConfigureDelegate = configure;
|
||||
ConfigureServicesDelegate = configureServices ?? ApplicationStartup.DefaultBuildServiceProvider;
|
||||
}
|
||||
|
||||
public ConfigureServicesDelegate ConfigureServicesDelegate { get; }
|
||||
public Action<IApplicationBuilder> ConfigureDelegate { get; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
"Microsoft.Framework.Runtime.Interfaces": "1.0.0-*",
|
||||
"Microsoft.AspNet.FileProviders": "1.0.0-*",
|
||||
"Microsoft.AspNet.Http.Core": "1.0.0-*",
|
||||
"Microsoft.AspNet.Http.Extensions": "1.0.0-*",
|
||||
"Microsoft.Framework.Logging": "1.0.0-*",
|
||||
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
|
||||
"Newtonsoft.Json": "6.0.6"
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using Microsoft.AspNet.RequestContainer;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Builder
|
||||
{
|
||||
public static class ContainerExtensions
|
||||
{
|
||||
public static IApplicationBuilder UseRequestServices(this IApplicationBuilder builder)
|
||||
{
|
||||
return builder.UseMiddleware<ContainerMiddleware>();
|
||||
}
|
||||
|
||||
// Review: what do we use these for?
|
||||
|
||||
public static IApplicationBuilder UseRequestServices(this IApplicationBuilder builder, IServiceProvider applicationServices)
|
||||
{
|
||||
// REVIEW: should this be doing fallback?
|
||||
builder.ApplicationServices = applicationServices;
|
||||
|
||||
return builder.UseMiddleware<ContainerMiddleware>();
|
||||
}
|
||||
|
||||
// Note: Manifests are lost after UseServices, services are flattened into ApplicationServices
|
||||
|
||||
public static IApplicationBuilder UseServices(this IApplicationBuilder builder, IServiceCollection applicationServices)
|
||||
{
|
||||
return builder.UseServices(services => services.Add(applicationServices));
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UseServices(this IApplicationBuilder builder, Action<IServiceCollection> configureServices)
|
||||
{
|
||||
return builder.UseServices(serviceCollection =>
|
||||
{
|
||||
configureServices(serviceCollection);
|
||||
return serviceCollection.BuildServiceProvider();
|
||||
});
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UseServices(this IApplicationBuilder builder, Func<IServiceCollection, IServiceProvider> configureServices)
|
||||
{
|
||||
// Import services from hosting/DNX as fallback
|
||||
var serviceCollection = HostingServices.Create(builder.ApplicationServices);
|
||||
|
||||
builder.ApplicationServices = configureServices(serviceCollection);
|
||||
|
||||
return builder.UseMiddleware<ContainerMiddleware>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>374a5b0c-3e93-4a23-a4a0-ee2ab6df7814</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"description": "ASP.NET 5 enables per-request scoping of services.",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Http.Extensions": "1.0.0-*",
|
||||
"Microsoft.AspNet.Hosting": "1.0.0-*",
|
||||
"Microsoft.Framework.OptionsModel": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": {},
|
||||
"dnxcore50": {
|
||||
"dependencies": {
|
||||
"System.Threading": "4.0.10-beta-*"
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -8,10 +8,10 @@ using Microsoft.AspNet.Builder;
|
|||
using Microsoft.AspNet.FeatureModel;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
using Microsoft.AspNet.Hosting.Server;
|
||||
using Microsoft.AspNet.Hosting.Startup;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.ConfigurationModel;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Microsoft.Framework.Runtime.Infrastructure;
|
||||
|
||||
namespace Microsoft.AspNet.TestHost
|
||||
|
|
@ -25,46 +25,63 @@ namespace Microsoft.AspNet.TestHost
|
|||
private IDisposable _appInstance;
|
||||
private bool _disposed = false;
|
||||
|
||||
public TestServer(IConfiguration config, IServiceProvider serviceProvider, Action<IApplicationBuilder> appStartup)
|
||||
// REVIEW: we can configure services via AppStartup or via hostContext.Services
|
||||
public TestServer(IConfiguration config, IServiceProvider serviceProvider, Action<IApplicationBuilder> configureApp, ConfigureServicesDelegate configureServices)
|
||||
{
|
||||
var appEnv = serviceProvider.GetRequiredService<IApplicationEnvironment>();
|
||||
var applicationLifetime = serviceProvider.GetRequiredService<IApplicationLifetime>();
|
||||
|
||||
HostingContext hostContext = new HostingContext()
|
||||
var hostContext = new HostingContext()
|
||||
{
|
||||
ApplicationName = appEnv.ApplicationName,
|
||||
ApplicationLifetime = applicationLifetime,
|
||||
ApplicationName = "Test App",
|
||||
Configuration = config,
|
||||
ServerFactory = this,
|
||||
ApplicationStartup = appStartup
|
||||
StartupMethods = new StartupMethods(configureApp, configureServices)
|
||||
};
|
||||
|
||||
var engine = serviceProvider.GetRequiredService<IHostingEngine>();
|
||||
_appInstance = engine.Start(hostContext);
|
||||
_appInstance = new HostingEngine(serviceProvider).Start(hostContext);
|
||||
}
|
||||
|
||||
public Uri BaseAddress { get; set; } = new Uri("http://localhost/");
|
||||
|
||||
public static TestServer Create(Action<IApplicationBuilder> app)
|
||||
public static TestServer Create(Action<IApplicationBuilder> configureApp)
|
||||
{
|
||||
return Create(CallContextServiceLocator.Locator.ServiceProvider, app, configureHostServices: null);
|
||||
return Create(CallContextServiceLocator.Locator.ServiceProvider, configureApp, configureServices: null);
|
||||
}
|
||||
|
||||
public static TestServer Create(Action<IApplicationBuilder> app, Action<IServiceCollection> configureHostServices)
|
||||
public static TestServer Create(Action<IApplicationBuilder> configureApp, Action<IServiceCollection> configureServices)
|
||||
{
|
||||
return Create(CallContextServiceLocator.Locator.ServiceProvider, app, configureHostServices);
|
||||
return Create(CallContextServiceLocator.Locator.ServiceProvider, configureApp,
|
||||
sc =>
|
||||
{
|
||||
if (configureServices != null)
|
||||
{
|
||||
configureServices(sc);
|
||||
}
|
||||
return sc.BuildServiceProvider();
|
||||
});
|
||||
}
|
||||
|
||||
public static TestServer Create(IServiceProvider serviceProvider, Action<IApplicationBuilder> app)
|
||||
public static TestServer Create(IServiceProvider serviceProvider, Action<IApplicationBuilder> configureApp)
|
||||
{
|
||||
return Create(serviceProvider, app, configureHostServices: null);
|
||||
return Create(serviceProvider, configureApp, configureServices: null);
|
||||
}
|
||||
|
||||
public static TestServer Create(IServiceProvider serviceProvider, Action<IApplicationBuilder> app, Action<IServiceCollection> configureHostServices)
|
||||
public static TestServer Create(IServiceProvider serviceProvider, Action<IApplicationBuilder> configureApp, Action<IServiceCollection> configureServices)
|
||||
{
|
||||
var appServices = HostingServices.Create(serviceProvider, configureHostServices).BuildServiceProvider();
|
||||
return Create(serviceProvider, configureApp,
|
||||
sc =>
|
||||
{
|
||||
if (configureServices != null)
|
||||
{
|
||||
configureServices(sc);
|
||||
}
|
||||
return sc.BuildServiceProvider();
|
||||
});
|
||||
}
|
||||
|
||||
public static TestServer Create(IServiceProvider serviceProvider, Action<IApplicationBuilder> configureApp, ConfigureServicesDelegate configureServices)
|
||||
{
|
||||
// REVIEW: do we need an overload that takes Config for Create?
|
||||
var config = new Configuration();
|
||||
return new TestServer(config, appServices, app);
|
||||
return new TestServer(config, serviceProvider, configureApp, configureServices);
|
||||
}
|
||||
|
||||
public HttpMessageHandler CreateHandler()
|
||||
|
|
@ -124,7 +141,7 @@ namespace Microsoft.AspNet.TestHost
|
|||
{
|
||||
public string Name
|
||||
{
|
||||
get { return TestServer.ServerName; }
|
||||
get { return ServerName; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
// 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");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Fakes
|
||||
{
|
||||
public class StartupWithNullConfigureServices
|
||||
{
|
||||
public IServiceProvider ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app) { }
|
||||
}
|
||||
}
|
||||
|
|
@ -18,32 +18,16 @@ namespace Microsoft.AspNet.Hosting
|
|||
{
|
||||
private readonly IList<StartInstance> _startInstances = new List<StartInstance>();
|
||||
|
||||
[Fact]
|
||||
public void HostingEngineCanBeResolvedWithDefaultServices()
|
||||
{
|
||||
var services = HostingServices.Create().BuildServiceProvider();
|
||||
|
||||
var engine = services.GetRequiredService<IHostingEngine>();
|
||||
|
||||
Assert.NotNull(engine);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HostingEngineCanBeStarted()
|
||||
{
|
||||
var services = HostingServices.Create().BuildServiceProvider();
|
||||
|
||||
var engine = services.GetRequiredService<IHostingEngine>();
|
||||
var applicationLifetime = services.GetRequiredService<IApplicationLifetime>();
|
||||
|
||||
var context = new HostingContext
|
||||
{
|
||||
ApplicationLifetime = applicationLifetime,
|
||||
ServerFactory = this,
|
||||
ApplicationName = "Microsoft.AspNet.Hosting.Tests"
|
||||
};
|
||||
|
||||
var engineStart = engine.Start(context);
|
||||
var engineStart = new HostingEngine().Start(context);
|
||||
|
||||
Assert.NotNull(engineStart);
|
||||
Assert.Equal(1, _startInstances.Count);
|
||||
|
|
@ -54,39 +38,97 @@ namespace Microsoft.AspNet.Hosting
|
|||
Assert.Equal(1, _startInstances[0].DisposeCalls);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ApplicationNameDefaultsToApplicationEnvironmentName()
|
||||
{
|
||||
var context = new HostingContext
|
||||
{
|
||||
ServerFactory = this
|
||||
};
|
||||
|
||||
var engine = new HostingEngine();
|
||||
|
||||
using (engine.Start(context))
|
||||
{
|
||||
Assert.Equal("Microsoft.AspNet.Hosting.Tests", context.ApplicationName);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnvDefaultsToDevelopmentIfNoConfig()
|
||||
{
|
||||
var context = new HostingContext
|
||||
{
|
||||
ServerFactory = this
|
||||
};
|
||||
|
||||
var engine = new HostingEngine();
|
||||
|
||||
using (engine.Start(context))
|
||||
{
|
||||
Assert.Equal("Development", context.EnvironmentName);
|
||||
var env = context.ApplicationServices.GetRequiredService<IHostingEnvironment>();
|
||||
Assert.Equal("Development", env.EnvironmentName);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnvDefaultsToDevelopmentConfigValueIfSpecified()
|
||||
{
|
||||
var vals = new Dictionary<string, string>
|
||||
{
|
||||
{ "ASPNET_ENV", "Staging" }
|
||||
};
|
||||
|
||||
var config = new Configuration()
|
||||
.Add(new MemoryConfigurationSource(vals));
|
||||
|
||||
var context = new HostingContext
|
||||
{
|
||||
ServerFactory = this,
|
||||
Configuration = config
|
||||
};
|
||||
|
||||
var engine = new HostingEngine();
|
||||
|
||||
using (engine.Start(context))
|
||||
{
|
||||
Assert.Equal("Staging", context.EnvironmentName);
|
||||
var env = context.ApplicationServices.GetRequiredService<IHostingEnvironment>();
|
||||
Assert.Equal("Staging", env.EnvironmentName);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebRootCanBeResolvedFromTheProjectJson()
|
||||
{
|
||||
var services = HostingServices.Create().BuildServiceProvider();
|
||||
var env = services.GetRequiredService<IHostingEnvironment>();
|
||||
var context = new HostingContext
|
||||
{
|
||||
ServerFactory = this
|
||||
};
|
||||
|
||||
var engineStart = new HostingEngine().Start(context);
|
||||
var env = context.ApplicationServices.GetRequiredService<IHostingEnvironment>();
|
||||
Assert.Equal(Path.GetFullPath("testroot"), env.WebRootPath);
|
||||
Assert.True(env.WebRootFileProvider.GetFileInfo("TextFile.txt").Exists);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_Environment_Name()
|
||||
{
|
||||
var services = HostingServices.Create().BuildServiceProvider();
|
||||
var env = services.GetRequiredService<IHostingEnvironment>();
|
||||
Assert.Equal("Development", env.EnvironmentName);
|
||||
|
||||
var config = new Configuration()
|
||||
.AddCommandLine(new string[] { "--ASPNET_ENV", "Overridden_Environment" });
|
||||
|
||||
services = HostingServices.Create(fallbackServices: null, configuration: config)
|
||||
.BuildServiceProvider();
|
||||
|
||||
env = services.GetRequiredService<IHostingEnvironment>();
|
||||
Assert.Equal("Overridden_Environment", env.EnvironmentName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsEnvironment_Extension_Is_Case_Insensitive()
|
||||
{
|
||||
var services = HostingServices.Create().BuildServiceProvider();
|
||||
var env = services.GetRequiredService<IHostingEnvironment>();
|
||||
Assert.True(env.IsEnvironment("Development"));
|
||||
Assert.True(env.IsEnvironment("developMent"));
|
||||
var context = new HostingContext
|
||||
{
|
||||
ServerFactory = this
|
||||
};
|
||||
|
||||
var engine = new HostingEngine();
|
||||
|
||||
using (engine.Start(context))
|
||||
{
|
||||
var env = context.ApplicationServices.GetRequiredService<IHostingEnvironment>();
|
||||
Assert.True(env.IsEnvironment("Development"));
|
||||
Assert.True(env.IsEnvironment("developMent"));
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize(IApplicationBuilder builder)
|
||||
|
|
|
|||
|
|
@ -1,210 +0,0 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using Microsoft.AspNet.Hosting.Fakes;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Tests
|
||||
{
|
||||
public class HostingServicesFacts
|
||||
{
|
||||
[Fact]
|
||||
public void CreateImportsServices()
|
||||
{
|
||||
// Arrange
|
||||
var fallbackServices = new ServiceCollection();
|
||||
fallbackServices.AddSingleton<IFakeSingletonService, FakeService>();
|
||||
var instance = new FakeService();
|
||||
var factoryInstance = new FakeFactoryService(instance);
|
||||
fallbackServices.AddInstance<IFakeServiceInstance>(instance);
|
||||
fallbackServices.AddTransient<IFakeService, FakeService>();
|
||||
fallbackServices.AddSingleton<IFactoryService>(serviceProvider => factoryInstance);
|
||||
fallbackServices.AddTransient<IFakeScopedService, FakeService>(); // Don't register in manifest
|
||||
|
||||
fallbackServices.AddInstance<IServiceManifest>(new ServiceManifest(
|
||||
new Type[] {
|
||||
typeof(IFakeServiceInstance),
|
||||
typeof(IFakeService),
|
||||
typeof(IFakeSingletonService),
|
||||
typeof(IFactoryService),
|
||||
typeof(INonexistentService)
|
||||
}));
|
||||
|
||||
var services = HostingServices.Create(fallbackServices.BuildServiceProvider());
|
||||
|
||||
// Act
|
||||
var provider = services.BuildServiceProvider();
|
||||
var singleton = provider.GetRequiredService<IFakeSingletonService>();
|
||||
var transient = provider.GetRequiredService<IFakeService>();
|
||||
var factory = provider.GetRequiredService<IFactoryService>();
|
||||
|
||||
// Assert
|
||||
Assert.Same(singleton, provider.GetRequiredService<IFakeSingletonService>());
|
||||
Assert.NotSame(transient, provider.GetRequiredService<IFakeService>());
|
||||
Assert.Same(instance, provider.GetRequiredService<IFakeServiceInstance>());
|
||||
Assert.Same(factoryInstance, factory);
|
||||
Assert.Same(factory.FakeService, instance);
|
||||
Assert.Null(provider.GetService<INonexistentService>());
|
||||
Assert.Null(provider.GetService<IFakeScopedService>()); // Make sure we don't leak non manifest services
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateCanAddAdditionalServices()
|
||||
{
|
||||
// Arrange
|
||||
var fallbackServices = new ServiceCollection();
|
||||
fallbackServices.AddTransient<IFakeService, FakeService>();
|
||||
fallbackServices.AddTransient<IFakeScopedService, FakeService>(); // Don't register in manifest
|
||||
|
||||
fallbackServices.AddInstance<IServiceManifest>(new ServiceManifest(
|
||||
new Type[] {
|
||||
typeof(IFakeService),
|
||||
}));
|
||||
|
||||
var instance = new FakeService();
|
||||
var factoryInstance = new FakeFactoryService(instance);
|
||||
|
||||
var services = HostingServices.Create(fallbackServices.BuildServiceProvider(),
|
||||
additionalHostServices =>
|
||||
{
|
||||
additionalHostServices.AddSingleton<IFakeSingletonService, FakeService>();
|
||||
additionalHostServices.AddInstance<IFakeServiceInstance>(instance);
|
||||
additionalHostServices.AddSingleton<IFactoryService>(serviceProvider => factoryInstance);
|
||||
});
|
||||
|
||||
// Act
|
||||
var provider = services.BuildServiceProvider();
|
||||
var singleton = provider.GetRequiredService<IFakeSingletonService>();
|
||||
var transient = provider.GetRequiredService<IFakeService>();
|
||||
var factory = provider.GetRequiredService<IFactoryService>();
|
||||
var manifest = provider.GetRequiredService<IServiceManifest>();
|
||||
|
||||
// Assert
|
||||
Assert.Same(singleton, provider.GetRequiredService<IFakeSingletonService>());
|
||||
Assert.NotSame(transient, provider.GetRequiredService<IFakeService>());
|
||||
Assert.Same(instance, provider.GetRequiredService<IFakeServiceInstance>());
|
||||
Assert.Same(factoryInstance, factory);
|
||||
Assert.Same(factory.FakeService, instance);
|
||||
Assert.Null(provider.GetService<INonexistentService>());
|
||||
Assert.Null(provider.GetService<IFakeScopedService>()); // Make sure we don't leak non manifest services
|
||||
Assert.Contains(typeof(IFakeSingletonService), manifest.Services);
|
||||
Assert.Contains(typeof(IFakeServiceInstance), manifest.Services);
|
||||
Assert.Contains(typeof(IFactoryService), manifest.Services);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateAdditionalServicesOverridesFallback()
|
||||
{
|
||||
// Arrange
|
||||
var fallbackServices = new ServiceCollection();
|
||||
fallbackServices.AddTransient<IFakeService, FakeService>();
|
||||
|
||||
fallbackServices.AddInstance<IServiceManifest>(new ServiceManifest(
|
||||
new Type[] {
|
||||
typeof(IFakeService),
|
||||
}));
|
||||
|
||||
var services = HostingServices.Create(fallbackServices.BuildServiceProvider(),
|
||||
additionalHostServices => additionalHostServices.AddSingleton<IFakeService, FakeService>());
|
||||
|
||||
// Act
|
||||
var provider = services.BuildServiceProvider();
|
||||
var singleton = provider.GetRequiredService<IFakeService>();
|
||||
|
||||
// Assert
|
||||
Assert.Same(singleton, provider.GetRequiredService<IFakeService>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateAdditionalServices_IncludesServicesInManifest()
|
||||
{
|
||||
// Arrange
|
||||
var fallbackServices = new ServiceCollection();
|
||||
fallbackServices.AddTransient<IFakeService, FakeService>();
|
||||
fallbackServices.AddInstance<IServiceManifest>(new ServiceManifest(
|
||||
new Type[] {
|
||||
typeof(IFakeService),
|
||||
}));
|
||||
var expectedInstance = new FakeService();
|
||||
var services = HostingServices.Create(
|
||||
fallbackServices.BuildServiceProvider(),
|
||||
additionalHostServices => additionalHostServices.AddInstance<IFakeServiceInstance>(expectedInstance));
|
||||
|
||||
// Act
|
||||
var provider = services.BuildServiceProvider();
|
||||
var instance = provider.GetRequiredService<IFakeServiceInstance>();
|
||||
var anotherInstance = provider.GetRequiredService<IFakeServiceInstance>();
|
||||
var manifest = provider.GetRequiredService<IServiceManifest>();
|
||||
|
||||
// Assert
|
||||
Assert.Same(expectedInstance, instance);
|
||||
Assert.Same(expectedInstance, anotherInstance);
|
||||
Assert.Contains(typeof(IFakeServiceInstance), manifest.Services);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanHideImportedServices()
|
||||
{
|
||||
// Arrange
|
||||
var fallbackServices = new ServiceCollection();
|
||||
var fallbackInstance = new FakeService();
|
||||
fallbackServices.AddInstance<IFakeService>(fallbackInstance);
|
||||
fallbackServices.AddInstance<IServiceManifest>(new ServiceManifest(new Type[] { typeof(IFakeService) }));
|
||||
|
||||
var services = HostingServices.Create(fallbackServices.BuildServiceProvider());
|
||||
var realInstance = new FakeService();
|
||||
services.AddInstance<IFakeService>(realInstance);
|
||||
|
||||
// Act
|
||||
var provider = services.BuildServiceProvider();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(realInstance, provider.GetRequiredService<IFakeService>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateThrowsWithNoManifest()
|
||||
{
|
||||
// Arrange
|
||||
var fallbackServices = new ServiceCollection();
|
||||
fallbackServices.AddSingleton<IFakeSingletonService, FakeService>();
|
||||
var instance = new FakeService();
|
||||
fallbackServices.AddInstance<IFakeServiceInstance>(instance);
|
||||
fallbackServices.AddTransient<IFakeService, FakeService>();
|
||||
|
||||
// Act
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => HostingServices.Create(fallbackServices.BuildServiceProvider()));
|
||||
|
||||
|
||||
// Assert
|
||||
Assert.Equal($"No service for type '{typeof(IServiceManifest).FullName}' has been registered.",
|
||||
exception.Message);
|
||||
}
|
||||
|
||||
private class ServiceManifest : IServiceManifest
|
||||
{
|
||||
public ServiceManifest(IEnumerable<Type> services)
|
||||
{
|
||||
Services = services;
|
||||
}
|
||||
|
||||
public IEnumerable<Type> Services { get; private set; }
|
||||
}
|
||||
|
||||
private class FakeFactoryService : IFactoryService
|
||||
{
|
||||
public FakeFactoryService(FakeService service)
|
||||
{
|
||||
FakeService = service;
|
||||
}
|
||||
|
||||
public IFakeService FakeService { get; private set; }
|
||||
|
||||
public int Value { get; private set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,6 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNet.Hosting.Tests
|
||||
{
|
||||
|
||||
public class StartupManagerTests : IFakeStartupCallback
|
||||
{
|
||||
private readonly IList<object> _configurationMethodCalledList = new List<object>();
|
||||
|
|
@ -20,16 +19,16 @@ namespace Microsoft.AspNet.Hosting.Tests
|
|||
[Fact]
|
||||
public void StartupClassMayHaveHostingServicesInjected()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection().AddHosting();
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddInstance<IFakeStartupCallback>(this);
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
|
||||
var loader = services.GetRequiredService<IStartupLoader>();
|
||||
|
||||
var diagnosticMessages = new List<string>();
|
||||
var startup = loader.LoadStartup("Microsoft.AspNet.Hosting.Tests", "WithServices", diagnosticMessages);
|
||||
var startup = ApplicationStartup.LoadStartupMethods(services, "Microsoft.AspNet.Hosting.Tests", "WithServices", diagnosticMessages);
|
||||
|
||||
startup.Invoke(new ApplicationBuilder(services));
|
||||
var app = new ApplicationBuilder(services);
|
||||
app.ApplicationServices = startup.ConfigureServicesDelegate(serviceCollection);
|
||||
startup.ConfigureDelegate(app);
|
||||
|
||||
Assert.Equal(2, _configurationMethodCalledList.Count);
|
||||
}
|
||||
|
|
@ -45,15 +44,14 @@ namespace Microsoft.AspNet.Hosting.Tests
|
|||
[InlineData("BaseClass")]
|
||||
public void StartupClassAddsConfigureServicesToApplicationServices(string environment)
|
||||
{
|
||||
var services = HostingServices.Create().BuildServiceProvider();
|
||||
var loader = services.GetRequiredService<IStartupLoader>();
|
||||
var services = new ServiceCollection().BuildServiceProvider();
|
||||
var diagnosticMesssages = new List<string>();
|
||||
|
||||
var startup = loader.LoadStartup("Microsoft.AspNet.Hosting.Tests", environment ?? "", diagnosticMesssages);
|
||||
var startup = ApplicationStartup.LoadStartupMethods(services, "Microsoft.AspNet.Hosting.Tests", environment ?? "", diagnosticMesssages);
|
||||
|
||||
var app = new ApplicationBuilder(services);
|
||||
|
||||
startup.Invoke(app);
|
||||
app.ApplicationServices = startup.ConfigureServicesDelegate(new ServiceCollection());
|
||||
startup.ConfigureDelegate(app);
|
||||
|
||||
var options = app.ApplicationServices.GetRequiredService<IOptions<FakeOptions>>().Options;
|
||||
Assert.NotNull(options);
|
||||
|
|
@ -61,92 +59,46 @@ namespace Microsoft.AspNet.Hosting.Tests
|
|||
Assert.Equal(environment, options.Environment);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Null")]
|
||||
[InlineData("FallbackProvider")]
|
||||
public void StartupClassConfigureServicesThatFallsbackToApplicationServices(string env)
|
||||
{
|
||||
var services = HostingServices.Create().BuildServiceProvider();
|
||||
var loader = services.GetRequiredService<IStartupLoader>();
|
||||
var diagnosticMessages = new List<string>();
|
||||
|
||||
var startup = loader.LoadStartup("Microsoft.AspNet.Hosting.Tests", env, diagnosticMessages);
|
||||
|
||||
var app = new ApplicationBuilder(services);
|
||||
|
||||
startup.Invoke(app);
|
||||
|
||||
Assert.Equal(services, app.ApplicationServices);
|
||||
}
|
||||
|
||||
// REVIEW: With the manifest change, Since the ConfigureServices are not imported, UseServices will mask what's in ConfigureServices
|
||||
// This will throw since ConfigureServices consumes manifest and then UseServices will blow up
|
||||
[Fact(Skip = "Review Failure")]
|
||||
public void StartupClassWithConfigureServicesAndUseServicesHidesConfigureServices()
|
||||
{
|
||||
var services = HostingServices.Create().BuildServiceProvider();
|
||||
var loader = services.GetRequiredService<IStartupLoader>();
|
||||
var diagnosticMessages = new List<string>();
|
||||
|
||||
var startup = loader.LoadStartup("Microsoft.AspNet.Hosting.Tests", "UseServices", diagnosticMessages);
|
||||
|
||||
var app = new ApplicationBuilder(services);
|
||||
|
||||
startup.Invoke(app);
|
||||
|
||||
Assert.NotNull(app.ApplicationServices.GetRequiredService<FakeService>());
|
||||
Assert.Null(app.ApplicationServices.GetService<IFakeService>());
|
||||
|
||||
var options = app.ApplicationServices.GetRequiredService<IOptions<FakeOptions>>().Options;
|
||||
Assert.NotNull(options);
|
||||
Assert.Equal("Configured", options.Message);
|
||||
Assert.False(options.Configured); // Options never resolved from inner containers
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartupWithNoConfigureThrows()
|
||||
{
|
||||
var serviceCollection = HostingServices.Create();
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddInstance<IFakeStartupCallback>(this);
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
var loader = services.GetRequiredService<IStartupLoader>();
|
||||
var diagnosticMessages = new List<string>();
|
||||
|
||||
var ex = Assert.Throws<Exception>(() => loader.LoadStartup("Microsoft.AspNet.Hosting.Tests", "Boom", diagnosticMessages));
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => ApplicationStartup.LoadStartupMethods(services, "Microsoft.AspNet.Hosting.Tests", "Boom", diagnosticMessages));
|
||||
Assert.Equal("A method named 'ConfigureBoom' or 'Configure' in the type 'Microsoft.AspNet.Hosting.Fakes.StartupBoom' could not be found.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartupWithConfigureServicesNotResolvedThrows()
|
||||
public void StartupClassCanHandleConfigureServicesThatReturnsNull()
|
||||
{
|
||||
var serviceCollection = HostingServices.Create();
|
||||
var serviceCollection = new ServiceCollection();
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
var loader = services.GetRequiredService<IStartupLoader>();
|
||||
|
||||
var diagnosticMessages = new List<string>();
|
||||
|
||||
var startup = loader.LoadStartup("Microsoft.AspNet.Hosting.Tests", "WithConfigureServicesNotResolved", diagnosticMessages);
|
||||
|
||||
var startup = ApplicationStartup.LoadStartupMethods(services, "Microsoft.AspNet.Hosting.Tests", "WithNullConfigureServices", diagnosticMessages);
|
||||
|
||||
var app = new ApplicationBuilder(services);
|
||||
|
||||
var ex = Assert.Throws<Exception>(() => startup.Invoke(app));
|
||||
|
||||
Assert.Equal("Could not resolve a service of type 'System.Int32' for the parameter 'notAService' of method 'Configure' on type 'Microsoft.AspNet.Hosting.Fakes.StartupWithConfigureServicesNotResolved'.", ex.Message);
|
||||
app.ApplicationServices = startup.ConfigureServicesDelegate(new ServiceCollection());
|
||||
Assert.NotNull(app.ApplicationServices);
|
||||
startup.ConfigureDelegate(app);
|
||||
Assert.NotNull(app.ApplicationServices);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartupClassWithConfigureServicesShouldMakeServiceAvailableInConfigure()
|
||||
{
|
||||
var serviceCollection = HostingServices.Create();
|
||||
var serviceCollection = new ServiceCollection();
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
var loader = services.GetRequiredService<IStartupLoader>();
|
||||
|
||||
var app = new ApplicationBuilder(services);
|
||||
|
||||
var diagnosticMessages = new List<string>();
|
||||
var startup = loader.LoadStartup("Microsoft.AspNet.Hosting.Tests", "WithConfigureServices", diagnosticMessages);
|
||||
var startup = ApplicationStartup.LoadStartupMethods(services, "Microsoft.AspNet.Hosting.Tests", "WithConfigureServices", diagnosticMessages);
|
||||
|
||||
startup.Invoke(app);
|
||||
var app = new ApplicationBuilder(services);
|
||||
app.ApplicationServices = startup.ConfigureServicesDelegate(serviceCollection);
|
||||
startup.ConfigureDelegate(app);
|
||||
|
||||
var foo = app.ApplicationServices.GetRequiredService<StartupWithConfigureServices.IFoo>();
|
||||
Assert.True(foo.Invoked);
|
||||
|
|
|
|||
|
|
@ -1,98 +0,0 @@
|
|||
// 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.Builder;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.RequestContainer;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Hosting.Tests
|
||||
{
|
||||
public class RequestServicesContainerFacts
|
||||
{
|
||||
[Fact]
|
||||
public void RequestServicesAvailableOnlyAfterRequestServices()
|
||||
{
|
||||
var baseServiceProvider = HostingServices.Create().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);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void EnsureRequestServicesSetsRequestServices(bool initializeApplicationServices)
|
||||
{
|
||||
var baseServiceProvider = HostingServices.Create().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, baseServiceProvider))
|
||||
{
|
||||
await next.Invoke(c);
|
||||
}
|
||||
});
|
||||
bool foundRequestServicesAfter = false;
|
||||
builder.Use(next => async c =>
|
||||
{
|
||||
foundRequestServicesAfter = c.RequestServices != null;
|
||||
await next.Invoke(c);
|
||||
});
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
if (initializeApplicationServices)
|
||||
{
|
||||
context.ApplicationServices = baseServiceProvider;
|
||||
}
|
||||
builder.Build().Invoke(context);
|
||||
Assert.False(foundRequestServicesBefore);
|
||||
Assert.True(foundRequestServicesAfter);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(typeof(IHostingEnvironment))]
|
||||
[InlineData(typeof(ILoggerFactory))]
|
||||
[InlineData(typeof(IHttpContextAccessor))]
|
||||
[InlineData(typeof(IApplicationLifetime))]
|
||||
public void UseRequestServicesHostingImportedServicesAreDefined(Type service)
|
||||
{
|
||||
var baseServiceProvider = HostingServices.Create().BuildServiceProvider();
|
||||
var builder = new ApplicationBuilder(baseServiceProvider);
|
||||
|
||||
builder.UseRequestServices();
|
||||
|
||||
var fromAppServices = builder.ApplicationServices.GetRequiredService(service);
|
||||
|
||||
Assert.NotNull(fromAppServices);
|
||||
Assert.Equal(baseServiceProvider.GetRequiredService(service), fromAppServices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
"dependencies": {
|
||||
"Microsoft.AspNet.Hosting": "1.0.0-*",
|
||||
"Microsoft.AspNet.Owin": "1.0.0-*",
|
||||
"Microsoft.AspNet.RequestContainer": "1.0.0-*",
|
||||
"Microsoft.Framework.OptionsModel": "1.0.0-*",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
},
|
||||
"frameworks": {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.FeatureModel;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.TestHost
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
// 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 System.Runtime.Versioning;
|
||||
using Microsoft.Framework.Runtime;
|
||||
|
||||
namespace Microsoft.AspNet.TestHost
|
||||
{
|
||||
public class TestApplicationEnvironment : IApplicationEnvironment
|
||||
{
|
||||
public string ApplicationName
|
||||
{
|
||||
get { return "Test App environment"; }
|
||||
}
|
||||
|
||||
public string Version
|
||||
{
|
||||
get { return "1.0.0"; }
|
||||
}
|
||||
|
||||
public string ApplicationBasePath
|
||||
{
|
||||
get { return Environment.CurrentDirectory; }
|
||||
}
|
||||
|
||||
public string Configuration
|
||||
{
|
||||
get { return "Test"; }
|
||||
}
|
||||
|
||||
public FrameworkName RuntimeFramework
|
||||
{
|
||||
get { return new FrameworkName(".NETFramework", new Version(4, 5)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,9 +20,7 @@ namespace Microsoft.AspNet.TestHost
|
|||
|
||||
public TestClientTests()
|
||||
{
|
||||
_services = HostingServices.Create().BuildServiceProvider();
|
||||
|
||||
_server = TestServer.Create(_services, app => app.Run(ctx => Task.FromResult(0)));
|
||||
_server = TestServer.Create(app => app.Run(ctx => Task.FromResult(0)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -32,7 +30,7 @@ namespace Microsoft.AspNet.TestHost
|
|||
var expected = "GET Response";
|
||||
RequestDelegate appDelegate = ctx =>
|
||||
ctx.Response.WriteAsync(expected);
|
||||
var server = TestServer.Create(_services, app => app.Run(appDelegate));
|
||||
var server = TestServer.Create(app => app.Run(appDelegate));
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
|
|
@ -53,7 +51,7 @@ namespace Microsoft.AspNet.TestHost
|
|||
Assert.Equal("/", ctx.Request.Path.Value);
|
||||
return ctx.Response.WriteAsync(expected);
|
||||
};
|
||||
var server = TestServer.Create(_services, app => app.Run(appDelegate));
|
||||
var server = TestServer.Create(app => app.Run(appDelegate));
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
|
|
@ -74,7 +72,7 @@ namespace Microsoft.AspNet.TestHost
|
|||
Assert.Equal("/", ctx.Request.Path.Value);
|
||||
return ctx.Response.WriteAsync(expected);
|
||||
};
|
||||
var server = TestServer.Create(_services, app => app.Run(appDelegate));
|
||||
var server = TestServer.Create(app => app.Run(appDelegate));
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
|
|
@ -90,7 +88,7 @@ namespace Microsoft.AspNet.TestHost
|
|||
// Arrange
|
||||
RequestDelegate appDelegate = ctx =>
|
||||
ctx.Response.WriteAsync(new StreamReader(ctx.Request.Body).ReadToEnd() + " PUT Response");
|
||||
var server = TestServer.Create(_services, app => app.Run(appDelegate));
|
||||
var server = TestServer.Create(app => app.Run(appDelegate));
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
|
|
@ -107,7 +105,7 @@ namespace Microsoft.AspNet.TestHost
|
|||
// Arrange
|
||||
RequestDelegate appDelegate = async ctx =>
|
||||
await ctx.Response.WriteAsync(new StreamReader(ctx.Request.Body).ReadToEnd() + " POST Response");
|
||||
var server = TestServer.Create(_services, app => app.Run(appDelegate));
|
||||
var server = TestServer.Create(app => app.Run(appDelegate));
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -21,10 +21,8 @@ namespace Microsoft.AspNet.TestHost
|
|||
public void CreateWithDelegate()
|
||||
{
|
||||
// Arrange
|
||||
var services = HostingServices.Create().BuildServiceProvider();
|
||||
|
||||
// Act & Assert (Does not throw)
|
||||
TestServer.Create(services, app => { });
|
||||
TestServer.Create(app => { });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -37,6 +35,21 @@ namespace Microsoft.AspNet.TestHost
|
|||
Assert.Throws<InvalidOperationException>(() => TestServer.Create(services, new Startup().Configuration));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RequestServicesAutoCreated()
|
||||
{
|
||||
TestServer server = TestServer.Create(app =>
|
||||
{
|
||||
app.Run(context =>
|
||||
{
|
||||
return context.Response.WriteAsync("RequestServices:" + (context.RequestServices != null));
|
||||
});
|
||||
});
|
||||
|
||||
string result = await server.CreateClient().GetStringAsync("/path");
|
||||
Assert.Equal("RequestServices:True", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanAccessLogger()
|
||||
{
|
||||
|
|
@ -92,7 +105,8 @@ namespace Microsoft.AspNet.TestHost
|
|||
var accessor = app.ApplicationServices.GetRequiredService<ContextHolder>();
|
||||
return context.Response.WriteAsync("HasContext:" + (accessor.Accessor.HttpContext != null));
|
||||
});
|
||||
}, newHostServices => newHostServices.AddSingleton<ContextHolder>());
|
||||
},
|
||||
services => services.AddSingleton<ContextHolder>().BuildServiceProvider());
|
||||
|
||||
string result = await server.CreateClient().GetStringAsync("/path");
|
||||
Assert.Equal("HasContext:True", result);
|
||||
|
|
|
|||
Loading…
Reference in New Issue