Merge branch 'release' of github.com:aspnet/Hosting into release
This commit is contained in:
commit
5fec478747
|
|
@ -1,6 +1,6 @@
|
||||||
Hosting
|
Hosting
|
||||||
=======
|
=======
|
||||||
|
|
||||||
The Hosting repo contains code required to host an ASP.NET vNext application, it is the entry point used when self-hosting an application.
|
The Hosting repo contains code required to host an ASP.NET 5 application, it is the entry point used when self-hosting an application.
|
||||||
|
|
||||||
This project is part of ASP.NET vNext. You can find samples, documentation and getting started instructions for ASP.NET vNext at the [Home](https://github.com/aspnet/home) repo.
|
This project is part of ASP.NET 5. You can find samples, documentation and getting started instructions for ASP.NET 5 at the [Home](https://github.com/aspnet/home) repo.
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,10 @@ IF EXIST packages\KoreBuild goto run
|
||||||
.nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
|
.nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
|
||||||
.nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion
|
.nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion
|
||||||
|
|
||||||
IF "%SKIP_KRE_INSTALL%"=="1" goto run
|
IF "%SKIP_DOTNET_INSTALL%"=="1" goto run
|
||||||
CALL packages\KoreBuild\build\kvm upgrade -runtime CLR -x86
|
CALL packages\KoreBuild\build\dotnetsdk upgrade -runtime CLR -x86
|
||||||
CALL packages\KoreBuild\build\kvm install default -runtime CoreCLR -x86
|
CALL packages\KoreBuild\build\dotnetsdk install default -runtime CoreCLR -x86
|
||||||
|
|
||||||
:run
|
:run
|
||||||
CALL packages\KoreBuild\build\kvm use default -runtime CLR -x86
|
CALL packages\KoreBuild\build\dotnetsdk use default -runtime CLR -x86
|
||||||
packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %*
|
packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %*
|
||||||
|
|
|
||||||
4
build.sh
4
build.sh
|
|
@ -28,11 +28,11 @@ if test ! -d packages/KoreBuild; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! type k > /dev/null 2>&1; then
|
if ! type k > /dev/null 2>&1; then
|
||||||
source packages/KoreBuild/build/kvm.sh
|
source packages/KoreBuild/build/dotnetsdk.sh
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! type k > /dev/null 2>&1; then
|
if ! type k > /dev/null 2>&1; then
|
||||||
kvm upgrade
|
dotnetsdk upgrade
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@"
|
mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Microsoft.AspNet.Http;
|
|
||||||
using Microsoft.AspNet.FeatureModel;
|
using Microsoft.AspNet.FeatureModel;
|
||||||
using Microsoft.AspNet.PipelineCore;
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.Http.Core;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Hosting.Builder
|
namespace Microsoft.AspNet.Hosting.Builder
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Microsoft.AspNet.Hosting
|
||||||
internal class ConfigureHostingEnvironment : IConfigureHostingEnvironment
|
internal class ConfigureHostingEnvironment : IConfigureHostingEnvironment
|
||||||
{
|
{
|
||||||
private IConfiguration _config;
|
private IConfiguration _config;
|
||||||
private const string EnvironmentKey = "KRE_ENV";
|
private const string EnvironmentKey = "ASPNET_ENV";
|
||||||
|
|
||||||
public ConfigureHostingEnvironment(IConfiguration config)
|
public ConfigureHostingEnvironment(IConfiguration config)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,20 @@ namespace Microsoft.AspNet.Hosting
|
||||||
private readonly IStartupManager _startupManager;
|
private readonly IStartupManager _startupManager;
|
||||||
private readonly IApplicationBuilderFactory _builderFactory;
|
private readonly IApplicationBuilderFactory _builderFactory;
|
||||||
private readonly IHttpContextFactory _httpContextFactory;
|
private readonly IHttpContextFactory _httpContextFactory;
|
||||||
|
private readonly IHttpContextAccessor _contextAccessor;
|
||||||
|
|
||||||
public HostingEngine(
|
public HostingEngine(
|
||||||
IServerManager serverManager,
|
IServerManager serverManager,
|
||||||
IStartupManager startupManager,
|
IStartupManager startupManager,
|
||||||
IApplicationBuilderFactory builderFactory,
|
IApplicationBuilderFactory builderFactory,
|
||||||
IHttpContextFactory httpContextFactory)
|
IHttpContextFactory httpContextFactory,
|
||||||
|
IHttpContextAccessor contextAccessor)
|
||||||
{
|
{
|
||||||
_serverManager = serverManager;
|
_serverManager = serverManager;
|
||||||
_startupManager = startupManager;
|
_startupManager = startupManager;
|
||||||
_builderFactory = builderFactory;
|
_builderFactory = builderFactory;
|
||||||
_httpContextFactory = httpContextFactory;
|
_httpContextFactory = httpContextFactory;
|
||||||
|
_contextAccessor = contextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDisposable Start(HostingContext context)
|
public IDisposable Start(HostingContext context)
|
||||||
|
|
@ -37,7 +40,7 @@ namespace Microsoft.AspNet.Hosting
|
||||||
EnsureApplicationDelegate(context);
|
EnsureApplicationDelegate(context);
|
||||||
|
|
||||||
var applicationLifetime = (ApplicationLifetime)context.Services.GetRequiredService<IApplicationLifetime>();
|
var applicationLifetime = (ApplicationLifetime)context.Services.GetRequiredService<IApplicationLifetime>();
|
||||||
var pipeline = new PipelineInstance(_httpContextFactory, context.ApplicationDelegate);
|
var pipeline = new PipelineInstance(_httpContextFactory, context.ApplicationDelegate, _contextAccessor);
|
||||||
var server = context.ServerFactory.Start(context.Server, pipeline.Invoke);
|
var server = context.ServerFactory.Start(context.Server, pipeline.Invoke);
|
||||||
|
|
||||||
return new Disposable(() =>
|
return new Disposable(() =>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNet.FileSystems;
|
using Microsoft.AspNet.FileProviders;
|
||||||
using Microsoft.Framework.Runtime;
|
using Microsoft.Framework.Runtime;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Hosting
|
namespace Microsoft.AspNet.Hosting
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNet.Hosting
|
||||||
{
|
{
|
||||||
EnvironmentName = DefaultEnvironmentName;
|
EnvironmentName = DefaultEnvironmentName;
|
||||||
WebRoot = HostingUtilities.GetWebRoot(appEnvironment.ApplicationBasePath);
|
WebRoot = HostingUtilities.GetWebRoot(appEnvironment.ApplicationBasePath);
|
||||||
WebRootFileSystem = new PhysicalFileSystem(WebRoot);
|
WebRootFileProvider = new PhysicalFileProvider(WebRoot);
|
||||||
foreach (var configure in configures)
|
foreach (var configure in configures)
|
||||||
{
|
{
|
||||||
configure.Configure(this);
|
configure.Configure(this);
|
||||||
|
|
@ -26,6 +26,6 @@ namespace Microsoft.AspNet.Hosting
|
||||||
|
|
||||||
public string WebRoot { get; private set; }
|
public string WebRoot { get; private set; }
|
||||||
|
|
||||||
public IFileSystem WebRootFileSystem { get; set; }
|
public IFileProvider WebRootFileProvider { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +45,7 @@ namespace Microsoft.AspNet.Hosting
|
||||||
public HostingManifest(IServiceProvider fallback)
|
public HostingManifest(IServiceProvider fallback)
|
||||||
{
|
{
|
||||||
var manifest = fallback.GetRequiredService<IServiceManifest>();
|
var manifest = fallback.GetRequiredService<IServiceManifest>();
|
||||||
Services = new Type[] { typeof(ITypeActivator), typeof(IHostingEnvironment), typeof(ILoggerFactory) }
|
Services = new Type[] { typeof(ITypeActivator), typeof(IHostingEnvironment), typeof(ILoggerFactory), typeof(IHttpContextAccessor) }
|
||||||
.Concat(manifest.Services).Distinct();
|
.Concat(manifest.Services).Distinct();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,8 @@ namespace Microsoft.Framework.DependencyInjection
|
||||||
services.AddTypeActivator(configuration);
|
services.AddTypeActivator(configuration);
|
||||||
// TODO: Do we expect this to be provide by the runtime eventually?
|
// TODO: Do we expect this to be provide by the runtime eventually?
|
||||||
services.AddLogging(configuration);
|
services.AddLogging(configuration);
|
||||||
// REVIEW: okay to use existing hosting environment/httpcontext if specified?
|
|
||||||
services.TryAdd(describer.Singleton<IHostingEnvironment, HostingEnvironment>());
|
services.TryAdd(describer.Singleton<IHostingEnvironment, HostingEnvironment>());
|
||||||
|
services.TryAdd(describer.Singleton<IHttpContextAccessor, HttpContextAccessor>());
|
||||||
// TODO: Remove this once we have IHttpContextAccessor
|
|
||||||
services.AddContextAccessor(configuration);
|
|
||||||
|
|
||||||
// REVIEW: don't try add because we pull out IEnumerable<IConfigureHostingEnvironment>?
|
// REVIEW: don't try add because we pull out IEnumerable<IConfigureHostingEnvironment>?
|
||||||
services.AddInstance<IConfigureHostingEnvironment>(new ConfigureHostingEnvironment(configuration));
|
services.AddInstance<IConfigureHostingEnvironment>(new ConfigureHostingEnvironment(configuration));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
// 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;
|
||||||
|
#if ASPNET50
|
||||||
|
using System.Runtime.Remoting.Messaging;
|
||||||
|
using System.Runtime.Remoting;
|
||||||
|
#elif ASPNETCORE50
|
||||||
|
using System.Threading;
|
||||||
|
#endif
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Hosting
|
||||||
|
{
|
||||||
|
public class HttpContextAccessor : IHttpContextAccessor
|
||||||
|
{
|
||||||
|
#if ASPNET50
|
||||||
|
private const string LogicalDataKey = "__HttpContext_Current__";
|
||||||
|
|
||||||
|
public HttpContext Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var handle = CallContext.LogicalGetData(LogicalDataKey) as ObjectHandle;
|
||||||
|
return handle != null ? handle.Unwrap() as HttpContext : null;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
CallContext.LogicalSetData(LogicalDataKey, new ObjectHandle(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif ASPNETCORE50
|
||||||
|
private AsyncLocal<HttpContext> _httpContextCurrent = new AsyncLocal<HttpContext>();
|
||||||
|
public HttpContext Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _httpContextCurrent.Value;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_httpContextCurrent.Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Microsoft.AspNet.FileSystems;
|
using Microsoft.AspNet.FileProviders;
|
||||||
using Microsoft.Framework.Runtime;
|
using Microsoft.Framework.Runtime;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Hosting
|
namespace Microsoft.AspNet.Hosting
|
||||||
|
|
@ -13,6 +13,6 @@ namespace Microsoft.AspNet.Hosting
|
||||||
|
|
||||||
string WebRoot { get; }
|
string WebRoot { get; }
|
||||||
|
|
||||||
IFileSystem WebRootFileSystem { get; set; }
|
IFileProvider WebRootFileProvider { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Hosting
|
||||||
|
{
|
||||||
|
public interface IHttpContextAccessor
|
||||||
|
{
|
||||||
|
HttpContext Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,9 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.AspNet.Http;
|
|
||||||
using Microsoft.AspNet.Hosting.Builder;
|
using Microsoft.AspNet.Hosting.Builder;
|
||||||
using Microsoft.AspNet.Hosting.Server;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Hosting
|
namespace Microsoft.AspNet.Hosting
|
||||||
{
|
{
|
||||||
|
|
@ -14,16 +12,19 @@ namespace Microsoft.AspNet.Hosting
|
||||||
{
|
{
|
||||||
private readonly IHttpContextFactory _httpContextFactory;
|
private readonly IHttpContextFactory _httpContextFactory;
|
||||||
private readonly RequestDelegate _requestDelegate;
|
private readonly RequestDelegate _requestDelegate;
|
||||||
|
private readonly IHttpContextAccessor _contextAccessor;
|
||||||
|
|
||||||
public PipelineInstance(IHttpContextFactory httpContextFactory, RequestDelegate requestDelegate)
|
public PipelineInstance(IHttpContextFactory httpContextFactory, RequestDelegate requestDelegate, IHttpContextAccessor contextAccessor)
|
||||||
{
|
{
|
||||||
_httpContextFactory = httpContextFactory;
|
_httpContextFactory = httpContextFactory;
|
||||||
_requestDelegate = requestDelegate;
|
_requestDelegate = requestDelegate;
|
||||||
|
_contextAccessor = contextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Invoke(object serverEnvironment)
|
public Task Invoke(object serverEnvironment)
|
||||||
{
|
{
|
||||||
var httpContext = _httpContextFactory.CreateHttpContext(serverEnvironment);
|
var httpContext = _httpContextFactory.CreateHttpContext(serverEnvironment);
|
||||||
|
_contextAccessor.Value = httpContext;
|
||||||
return _requestDelegate(httpContext);
|
return _requestDelegate(httpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.Framework.ConfigurationModel;
|
using Microsoft.Framework.ConfigurationModel;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||||
|
using Microsoft.Framework.Logging;
|
||||||
using Microsoft.Framework.Runtime;
|
using Microsoft.Framework.Runtime;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Hosting
|
namespace Microsoft.AspNet.Hosting
|
||||||
|
|
@ -52,6 +53,7 @@ namespace Microsoft.AspNet.Hosting
|
||||||
};
|
};
|
||||||
|
|
||||||
var engine = services.GetRequiredService<IHostingEngine>();
|
var engine = services.GetRequiredService<IHostingEngine>();
|
||||||
|
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
|
||||||
var appShutdownService = _serviceProvider.GetRequiredService<IApplicationShutdown>();
|
var appShutdownService = _serviceProvider.GetRequiredService<IApplicationShutdown>();
|
||||||
var shutdownHandle = new ManualResetEvent(false);
|
var shutdownHandle = new ManualResetEvent(false);
|
||||||
|
|
||||||
|
|
@ -59,7 +61,15 @@ namespace Microsoft.AspNet.Hosting
|
||||||
|
|
||||||
appShutdownService.ShutdownRequested.Register(() =>
|
appShutdownService.ShutdownRequested.Register(() =>
|
||||||
{
|
{
|
||||||
serverShutdown.Dispose();
|
try
|
||||||
|
{
|
||||||
|
serverShutdown.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var logger = loggerFactory.Create<Program>();
|
||||||
|
logger.WriteError("TODO: Dispose threw an exception", ex);
|
||||||
|
}
|
||||||
shutdownHandle.Set();
|
shutdownHandle.Set();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ using System.Reflection;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||||
using Microsoft.Framework.OptionsModel;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Hosting.Startup
|
namespace Microsoft.AspNet.Hosting.Startup
|
||||||
{
|
{
|
||||||
|
|
@ -153,8 +152,6 @@ namespace Microsoft.AspNet.Hosting.Startup
|
||||||
if (servicesMethod != null)
|
if (servicesMethod != null)
|
||||||
{
|
{
|
||||||
var services = HostingServices.Create(builder.ApplicationServices);
|
var services = HostingServices.Create(builder.ApplicationServices);
|
||||||
// TODO: remove this once IHttpContextAccessor service is added
|
|
||||||
services.AddContextAccessor();
|
|
||||||
if (servicesMethod.ReturnType == typeof(IServiceProvider))
|
if (servicesMethod.ReturnType == typeof(IServiceProvider))
|
||||||
{
|
{
|
||||||
// IServiceProvider ConfigureServices(IServiceCollection)
|
// IServiceProvider ConfigureServices(IServiceCollection)
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
"version": "1.0.0-*",
|
"version": "1.0.0-*",
|
||||||
"description": "ASP.NET 5 core hosting infrastructure and startup logic for web applications.",
|
"description": "ASP.NET 5 core hosting infrastructure and startup logic for web applications.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNet.FileSystems": "1.0.0-*",
|
"Microsoft.AspNet.FileProviders": "1.0.0-*",
|
||||||
"Microsoft.AspNet.PipelineCore": "1.0.0-*",
|
"Microsoft.AspNet.Http.Core": "1.0.0-*",
|
||||||
"Microsoft.Framework.Logging": "1.0.0-*",
|
"Microsoft.Framework.Logging": "1.0.0-*",
|
||||||
"Microsoft.Framework.OptionsModel": "1.0.0-*",
|
"Microsoft.Framework.OptionsModel": "1.0.0-*",
|
||||||
"Microsoft.Framework.Runtime.Interfaces": { "version": "1.0.0-*", "type": "build" },
|
"Microsoft.Framework.Runtime.Interfaces": { "version": "1.0.0-*", "type": "build" },
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,6 @@ namespace Microsoft.AspNet.Builder
|
||||||
// Import services from hosting/KRE as fallback
|
// Import services from hosting/KRE as fallback
|
||||||
var serviceCollection = HostingServices.Create(builder.ApplicationServices);
|
var serviceCollection = HostingServices.Create(builder.ApplicationServices);
|
||||||
|
|
||||||
// TODO: remove this once IHttpContextAccessor service is added
|
|
||||||
serviceCollection.AddContextAccessor();
|
|
||||||
|
|
||||||
// REVIEW: serviceCollection has the merged services, manifests are lost after this
|
|
||||||
builder.ApplicationServices = configureServices(serviceCollection);
|
builder.ApplicationServices = configureServices(serviceCollection);
|
||||||
|
|
||||||
return builder.UseMiddleware<ContainerMiddleware>();
|
return builder.UseMiddleware<ContainerMiddleware>();
|
||||||
|
|
|
||||||
|
|
@ -2,72 +2,21 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
#if ASPNET50
|
|
||||||
using System.Runtime.Remoting.Messaging;
|
|
||||||
#endif
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
|
||||||
#if ASPNET50
|
|
||||||
using System.Runtime.Remoting;
|
|
||||||
#endif
|
|
||||||
namespace Microsoft.AspNet.RequestContainer
|
namespace Microsoft.AspNet.RequestContainer
|
||||||
{
|
{
|
||||||
public class ContainerMiddleware
|
public class ContainerMiddleware
|
||||||
{
|
{
|
||||||
private const string LogicalDataKey = "__HttpContext_Current__";
|
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IServiceProvider _rootServiceProvider;
|
private readonly IServiceProvider _services;
|
||||||
private readonly IContextAccessor<HttpContext> _rootHttpContextAccessor;
|
|
||||||
private readonly IServiceScopeFactory _rootServiceScopeFactory;
|
|
||||||
|
|
||||||
public ContainerMiddleware(
|
public ContainerMiddleware(RequestDelegate next, IServiceProvider services)
|
||||||
RequestDelegate next,
|
|
||||||
IServiceProvider rootServiceProvider,
|
|
||||||
IContextAccessor<HttpContext> rootHttpContextAccessor,
|
|
||||||
IServiceScopeFactory rootServiceScopeFactory)
|
|
||||||
{
|
{
|
||||||
if (rootServiceProvider == null)
|
_services = services;
|
||||||
{
|
|
||||||
throw new ArgumentNullException("rootServiceProvider");
|
|
||||||
}
|
|
||||||
if (rootHttpContextAccessor == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("rootHttpContextAccessor");
|
|
||||||
}
|
|
||||||
if (rootServiceScopeFactory == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("rootServiceScopeFactory");
|
|
||||||
}
|
|
||||||
|
|
||||||
_next = next;
|
_next = next;
|
||||||
_rootServiceProvider = rootServiceProvider;
|
|
||||||
_rootServiceScopeFactory = rootServiceScopeFactory;
|
|
||||||
_rootHttpContextAccessor = rootHttpContextAccessor;
|
|
||||||
|
|
||||||
_rootHttpContextAccessor.SetContextSource(AccessRootHttpContext, ExchangeRootHttpContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static HttpContext AccessRootHttpContext()
|
|
||||||
{
|
|
||||||
#if ASPNET50
|
|
||||||
var handle = CallContext.LogicalGetData(LogicalDataKey) as ObjectHandle;
|
|
||||||
return handle != null ? handle.Unwrap() as HttpContext : null;
|
|
||||||
#else
|
|
||||||
throw new Exception("TODO: CallContext not available");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static HttpContext ExchangeRootHttpContext(HttpContext httpContext)
|
|
||||||
{
|
|
||||||
#if ASPNET50
|
|
||||||
var prior = CallContext.LogicalGetData(LogicalDataKey) as ObjectHandle;
|
|
||||||
CallContext.LogicalSetData(LogicalDataKey, new ObjectHandle(httpContext));
|
|
||||||
return prior != null ? prior.Unwrap() as HttpContext : null;
|
|
||||||
#else
|
|
||||||
return null;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(HttpContext httpContext)
|
public async Task Invoke(HttpContext httpContext)
|
||||||
|
|
@ -77,22 +26,7 @@ namespace Microsoft.AspNet.RequestContainer
|
||||||
throw new Exception("TODO: nested request container scope? this is probably a mistake on your part?");
|
throw new Exception("TODO: nested request container scope? this is probably a mistake on your part?");
|
||||||
}
|
}
|
||||||
|
|
||||||
var priorApplicationServices = httpContext.ApplicationServices;
|
using (var container = RequestServicesContainer.EnsureRequestServices(httpContext, _services))
|
||||||
var priorRequestServices = httpContext.RequestServices;
|
|
||||||
|
|
||||||
var appServiceProvider = _rootServiceProvider;
|
|
||||||
var appServiceScopeFactory = _rootServiceScopeFactory;
|
|
||||||
var appHttpContextAccessor = _rootHttpContextAccessor;
|
|
||||||
|
|
||||||
if (priorApplicationServices != null &&
|
|
||||||
priorApplicationServices != appServiceProvider)
|
|
||||||
{
|
|
||||||
appServiceProvider = priorApplicationServices;
|
|
||||||
appServiceScopeFactory = priorApplicationServices.GetRequiredService<IServiceScopeFactory>();
|
|
||||||
appHttpContextAccessor = priorApplicationServices.GetRequiredService<IContextAccessor<HttpContext>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var container = new RequestServicesContainer(httpContext, appServiceScopeFactory, appHttpContextAccessor, appServiceProvider))
|
|
||||||
{
|
{
|
||||||
await _next.Invoke(httpContext);
|
await _next.Invoke(httpContext);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ namespace Microsoft.AspNet.RequestContainer
|
||||||
public RequestServicesContainer(
|
public RequestServicesContainer(
|
||||||
HttpContext context,
|
HttpContext context,
|
||||||
IServiceScopeFactory scopeFactory,
|
IServiceScopeFactory scopeFactory,
|
||||||
IContextAccessor<HttpContext> appContextAccessor,
|
|
||||||
IServiceProvider appServiceProvider)
|
IServiceProvider appServiceProvider)
|
||||||
{
|
{
|
||||||
if (scopeFactory == null)
|
if (scopeFactory == null)
|
||||||
|
|
@ -23,12 +22,6 @@ namespace Microsoft.AspNet.RequestContainer
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(context));
|
throw new ArgumentNullException(nameof(context));
|
||||||
}
|
}
|
||||||
if (appContextAccessor == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(appContextAccessor));
|
|
||||||
}
|
|
||||||
|
|
||||||
AppContextAccessor = appContextAccessor;
|
|
||||||
|
|
||||||
Context = context;
|
Context = context;
|
||||||
PriorAppServices = context.ApplicationServices;
|
PriorAppServices = context.ApplicationServices;
|
||||||
|
|
@ -36,23 +29,16 @@ namespace Microsoft.AspNet.RequestContainer
|
||||||
|
|
||||||
// Begin the scope
|
// Begin the scope
|
||||||
Scope = scopeFactory.CreateScope();
|
Scope = scopeFactory.CreateScope();
|
||||||
ScopeContextAccessor = Scope.ServiceProvider.GetRequiredService<IContextAccessor<HttpContext>>();
|
|
||||||
|
|
||||||
Context.ApplicationServices = appServiceProvider;
|
Context.ApplicationServices = appServiceProvider;
|
||||||
Context.RequestServices = Scope.ServiceProvider;
|
Context.RequestServices = Scope.ServiceProvider;
|
||||||
|
|
||||||
PriorAppHttpContext = AppContextAccessor.SetValue(context);
|
|
||||||
PriorScopeHttpContext = ScopeContextAccessor.SetValue(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpContext Context { get; set; }
|
private HttpContext Context { get; set; }
|
||||||
private IServiceProvider PriorAppServices { get; set; }
|
private IServiceProvider PriorAppServices { get; set; }
|
||||||
private IServiceProvider PriorRequestServices { get; set; }
|
private IServiceProvider PriorRequestServices { get; set; }
|
||||||
private HttpContext PriorAppHttpContext { get; set; }
|
|
||||||
private HttpContext PriorScopeHttpContext { get; set; }
|
|
||||||
private IServiceScope Scope { 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
|
// CONSIDER: this could be an extension method on HttpContext instead
|
||||||
public static RequestServicesContainer EnsureRequestServices(HttpContext httpContext, IServiceProvider services)
|
public static RequestServicesContainer EnsureRequestServices(HttpContext httpContext, IServiceProvider services)
|
||||||
|
|
@ -64,7 +50,6 @@ namespace Microsoft.AspNet.RequestContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
var serviceProvider = httpContext.ApplicationServices ?? services;
|
var serviceProvider = httpContext.ApplicationServices ?? services;
|
||||||
|
|
||||||
if (serviceProvider == null)
|
if (serviceProvider == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("TODO: services and httpContext.ApplicationServices are both null!");
|
throw new InvalidOperationException("TODO: services and httpContext.ApplicationServices are both null!");
|
||||||
|
|
@ -72,32 +57,27 @@ namespace Microsoft.AspNet.RequestContainer
|
||||||
|
|
||||||
// Matches constructor of RequestContainer
|
// Matches constructor of RequestContainer
|
||||||
var rootServiceProvider = serviceProvider.GetRequiredService<IServiceProvider>();
|
var rootServiceProvider = serviceProvider.GetRequiredService<IServiceProvider>();
|
||||||
var rootHttpContextAccessor = serviceProvider.GetRequiredService<IContextAccessor<HttpContext>>();
|
|
||||||
var rootServiceScopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
|
var rootServiceScopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
|
||||||
|
|
||||||
rootHttpContextAccessor.SetContextSource(ContainerMiddleware.AccessRootHttpContext, ContainerMiddleware.ExchangeRootHttpContext);
|
|
||||||
|
|
||||||
// Pre Scope setup
|
// Pre Scope setup
|
||||||
var priorApplicationServices = serviceProvider;
|
var priorApplicationServices = serviceProvider;
|
||||||
var priorRequestServices = serviceProvider;
|
var priorRequestServices = serviceProvider;
|
||||||
|
|
||||||
var appServiceProvider = rootServiceProvider;
|
var appServiceProvider = rootServiceProvider;
|
||||||
var appServiceScopeFactory = rootServiceScopeFactory;
|
var appServiceScopeFactory = rootServiceScopeFactory;
|
||||||
var appHttpContextAccessor = rootHttpContextAccessor;
|
|
||||||
|
|
||||||
if (priorApplicationServices != null &&
|
if (priorApplicationServices != null &&
|
||||||
priorApplicationServices != appServiceProvider)
|
priorApplicationServices != appServiceProvider)
|
||||||
{
|
{
|
||||||
appServiceProvider = priorApplicationServices;
|
appServiceProvider = priorApplicationServices;
|
||||||
appServiceScopeFactory = priorApplicationServices.GetRequiredService<IServiceScopeFactory>();
|
appServiceScopeFactory = priorApplicationServices.GetRequiredService<IServiceScopeFactory>();
|
||||||
appHttpContextAccessor = priorApplicationServices.GetRequiredService<IContextAccessor<HttpContext>>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates the scope and does the service swaps
|
// Creates the scope and does the service swaps
|
||||||
return new RequestServicesContainer(httpContext, appServiceScopeFactory, appHttpContextAccessor, appServiceProvider);
|
return new RequestServicesContainer(httpContext, appServiceScopeFactory, appServiceProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IDisposable Support
|
#region IDisposable Support
|
||||||
private bool disposedValue = false; // To detect redundant calls
|
private bool disposedValue = false; // To detect redundant calls
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|
@ -106,9 +86,6 @@ namespace Microsoft.AspNet.RequestContainer
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
ScopeContextAccessor.SetValue(PriorScopeHttpContext);
|
|
||||||
AppContextAccessor.SetValue(PriorAppHttpContext);
|
|
||||||
|
|
||||||
Context.RequestServices = PriorRequestServices;
|
Context.RequestServices = PriorRequestServices;
|
||||||
Context.ApplicationServices = PriorAppServices;
|
Context.ApplicationServices = PriorAppServices;
|
||||||
}
|
}
|
||||||
|
|
@ -122,10 +99,6 @@ namespace Microsoft.AspNet.RequestContainer
|
||||||
Context = null;
|
Context = null;
|
||||||
PriorAppServices = null;
|
PriorAppServices = null;
|
||||||
PriorRequestServices = null;
|
PriorRequestServices = null;
|
||||||
ScopeContextAccessor = null;
|
|
||||||
AppContextAccessor = null;
|
|
||||||
PriorAppHttpContext = null;
|
|
||||||
PriorScopeHttpContext = null;
|
|
||||||
|
|
||||||
disposedValue = true;
|
disposedValue = true;
|
||||||
}
|
}
|
||||||
|
|
@ -137,8 +110,6 @@ namespace Microsoft.AspNet.RequestContainer
|
||||||
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -8,6 +8,10 @@
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"aspnet50": {},
|
"aspnet50": {},
|
||||||
"aspnetcore50": {}
|
"aspnetcore50": {
|
||||||
|
"dependencies": {
|
||||||
|
"System.Threading": "4.0.10-beta-*"
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.FeatureModel;
|
using Microsoft.AspNet.FeatureModel;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
using Microsoft.AspNet.HttpFeature;
|
using Microsoft.AspNet.Http.Core;
|
||||||
using Microsoft.AspNet.PipelineCore;
|
using Microsoft.AspNet.Http.Interfaces;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.TestHost
|
namespace Microsoft.AspNet.TestHost
|
||||||
{
|
{
|
||||||
|
|
@ -38,6 +38,12 @@ namespace Microsoft.AspNet.TestHost
|
||||||
}
|
}
|
||||||
|
|
||||||
_next = next;
|
_next = next;
|
||||||
|
|
||||||
|
// PathString.StartsWithSegments that we use below requires the base path to not end in a slash.
|
||||||
|
if (pathBase.HasValue && pathBase.Value.EndsWith("/"))
|
||||||
|
{
|
||||||
|
pathBase = new PathString(pathBase.Value.Substring(0, pathBase.Value.Length - 1));
|
||||||
|
}
|
||||||
_pathBase = pathBase;
|
_pathBase = pathBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.AspNet.HttpFeature;
|
using Microsoft.AspNet.Http.Interfaces;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.TestHost
|
namespace Microsoft.AspNet.TestHost
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.AspNet.HttpFeature;
|
using Microsoft.AspNet.Http.Interfaces;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.TestHost
|
namespace Microsoft.AspNet.TestHost
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,6 @@ namespace Microsoft.AspNet.TestHost
|
||||||
public HttpMessageHandler CreateHandler()
|
public HttpMessageHandler CreateHandler()
|
||||||
{
|
{
|
||||||
var pathBase = BaseAddress == null ? PathString.Empty : PathString.FromUriComponent(BaseAddress);
|
var pathBase = BaseAddress == null ? PathString.Empty : PathString.FromUriComponent(BaseAddress);
|
||||||
if (pathBase.Equals(new PathString("/")))
|
|
||||||
{
|
|
||||||
// When we just have http://host/ the trailing slash is really part of the Path, not the PathBase.
|
|
||||||
pathBase = PathString.Empty;
|
|
||||||
}
|
|
||||||
return new ClientHandler(Invoke, pathBase);
|
return new ClientHandler(Invoke, pathBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ namespace Microsoft.AspNet.Hosting
|
||||||
var services = HostingServices.Create().BuildServiceProvider();
|
var services = HostingServices.Create().BuildServiceProvider();
|
||||||
var env = services.GetRequiredService<IHostingEnvironment>();
|
var env = services.GetRequiredService<IHostingEnvironment>();
|
||||||
Assert.Equal(Path.GetFullPath("testroot"), env.WebRoot);
|
Assert.Equal(Path.GetFullPath("testroot"), env.WebRoot);
|
||||||
Assert.True(env.WebRootFileSystem.GetFileInfo("TextFile.txt").Exists);
|
Assert.True(env.WebRootFileProvider.GetFileInfo("TextFile.txt").Exists);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(IApplicationBuilder builder)
|
public void Initialize(IApplicationBuilder builder)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.AspNet.Hosting.Builder;
|
using Microsoft.AspNet.Hosting.Builder;
|
||||||
using Microsoft.AspNet.Hosting.Server;
|
using Microsoft.AspNet.Hosting.Server;
|
||||||
using Microsoft.AspNet.Hosting.Startup;
|
using Microsoft.AspNet.Hosting.Startup;
|
||||||
using Microsoft.AspNet.PipelineCore;
|
using Microsoft.AspNet.Http.Core;
|
||||||
using Microsoft.AspNet.RequestContainer;
|
using Microsoft.AspNet.RequestContainer;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||||
|
|
@ -92,6 +92,7 @@ namespace Microsoft.AspNet.Hosting.Tests
|
||||||
[InlineData(typeof(ITypeActivator))]
|
[InlineData(typeof(ITypeActivator))]
|
||||||
[InlineData(typeof(IApplicationLifetime))]
|
[InlineData(typeof(IApplicationLifetime))]
|
||||||
[InlineData(typeof(ILoggerFactory))]
|
[InlineData(typeof(ILoggerFactory))]
|
||||||
|
[InlineData(typeof(IHttpContextAccessor))]
|
||||||
public void UseRequestServicesHostingImportedServicesAreDefined(Type service)
|
public void UseRequestServicesHostingImportedServicesAreDefined(Type service)
|
||||||
{
|
{
|
||||||
var baseServiceProvider = HostingServices.Create().BuildServiceProvider();
|
var baseServiceProvider = HostingServices.Create().BuildServiceProvider();
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNet.Hosting": "1.0.0-*",
|
"Microsoft.AspNet.Hosting": "1.0.0-*",
|
||||||
"Microsoft.AspNet.RequestContainer": "1.0.0-*",
|
"Microsoft.AspNet.RequestContainer": "1.0.0-*",
|
||||||
"Xunit.KRunner": "1.0.0-*"
|
"xunit.runner.kre": "1.0.0-*"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"aspnet50": { }
|
"aspnet50": { }
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
"test": "Xunit.KRunner"
|
"test": "xunit.runner.kre"
|
||||||
},
|
},
|
||||||
"webroot": "testroot"
|
"webroot": "testroot"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.FeatureModel;
|
using Microsoft.AspNet.FeatureModel;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
using Microsoft.AspNet.HttpFeature;
|
using Microsoft.AspNet.Http.Core;
|
||||||
using Microsoft.AspNet.PipelineCore;
|
using Microsoft.AspNet.Http.Interfaces;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.TestHost
|
namespace Microsoft.AspNet.TestHost
|
||||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNet.TestHost
|
||||||
Assert.Equal("example.com", context.Request.Host.Value);
|
Assert.Equal("example.com", context.Request.Host.Value);
|
||||||
|
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}, new PathString("/A/Path"));
|
}, new PathString("/A/Path/"));
|
||||||
var httpClient = new HttpClient(handler);
|
var httpClient = new HttpClient(handler);
|
||||||
return httpClient.GetAsync("https://example.com/A/Path/and/file.txt?and=query");
|
return httpClient.GetAsync("https://example.com/A/Path/and/file.txt?and=query");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ namespace Microsoft.AspNet.TestHost
|
||||||
// Arrange
|
// Arrange
|
||||||
var services = HostingServices.Create().BuildServiceProvider();
|
var services = HostingServices.Create().BuildServiceProvider();
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert (Does not throw)
|
||||||
Assert.DoesNotThrow(() => TestServer.Create(services, app => { }));
|
TestServer.Create(services, app => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -37,6 +37,23 @@ namespace Microsoft.AspNet.TestHost
|
||||||
Assert.Throws<InvalidOperationException>(() => TestServer.Create(services, new Startup().Configuration));
|
Assert.Throws<InvalidOperationException>(() => TestServer.Create(services, new Startup().Configuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CanAccessHttpContext()
|
||||||
|
{
|
||||||
|
var services = new ServiceCollection().BuildServiceProvider();
|
||||||
|
TestServer server = TestServer.Create(app =>
|
||||||
|
{
|
||||||
|
app.Run(context =>
|
||||||
|
{
|
||||||
|
var accessor = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>();
|
||||||
|
return context.Response.WriteAsync("HasContext:"+(accessor.Value != null));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
string result = await server.CreateClient().GetStringAsync("/path");
|
||||||
|
Assert.Equal("HasContext:True", result);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CreateInvokesApp()
|
public async Task CreateInvokesApp()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||||
"Xunit.KRunner": "1.0.0-*"
|
"xunit.runner.kre": "1.0.0-*"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
"test": "Xunit.KRunner"
|
"test": "xunit.runner.kre"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"aspnet50": { }
|
"aspnet50": { }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue