Adding UseContainer middleware
Assigns values to HttpContext.ApplicationServices and HttpContext.RequestServices as call passes through
This commit is contained in:
parent
aa0b52df4e
commit
c39a41bd9f
50
Hosting.sln
50
Hosting.sln
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.30203.2
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E0497F39-AFFB-4819-A116-E39E361915AB}"
|
||||
EndProject
|
||||
|
|
@ -15,9 +15,17 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Hosting.Te
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{C30C98CD-3D69-4AE9-B680-0E0E6D8834C6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KWebStartup.net45", "samples\KWebStartup\KWebStartup.net45.csproj", "{E9B21845-E51A-4B8C-AF0B-0C4CE16550BF}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.RequestContainer.net45", "src\Microsoft.AspNet.RequestContainer\Microsoft.AspNet.RequestContainer.net45.csproj", "{F4C7B46C-B39F-4172-9C3A-05352183D469}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KWebStartup.k10", "samples\KWebStartup\KWebStartup.k10.csproj", "{348007AA-AB91-48B2-98DB-57D068E2C1AE}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.RequestContainer.k10", "src\Microsoft.AspNet.RequestContainer\Microsoft.AspNet.RequestContainer.k10.csproj", "{FD9833B9-3FB1-4612-BBB4-64F539DB0F8B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "net45", "net45", "{93FB86DB-7D2A-46CE-AFD2-0B53E6A8CF69}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "k10", "k10", "{EB784E77-FD42-46EC-9C8C-502B78962407}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KWebStartup.k10", "samples\KWebStartup\KWebStartup.k10.csproj", "{C0235BA1-9198-42C0-92D8-7578E9B9D96B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KWebStartup.net45", "samples\KWebStartup\KWebStartup.net45.csproj", "{B5939234-73ED-4DAD-A2C6-D61AA6DFB406}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
|
@ -37,23 +45,35 @@ Global
|
|||
{80588AF3-6B14-4D11-9DC4-1EF6453B54C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{80588AF3-6B14-4D11-9DC4-1EF6453B54C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{80588AF3-6B14-4D11-9DC4-1EF6453B54C9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E9B21845-E51A-4B8C-AF0B-0C4CE16550BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E9B21845-E51A-4B8C-AF0B-0C4CE16550BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E9B21845-E51A-4B8C-AF0B-0C4CE16550BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E9B21845-E51A-4B8C-AF0B-0C4CE16550BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{348007AA-AB91-48B2-98DB-57D068E2C1AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{348007AA-AB91-48B2-98DB-57D068E2C1AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{348007AA-AB91-48B2-98DB-57D068E2C1AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{348007AA-AB91-48B2-98DB-57D068E2C1AE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F4C7B46C-B39F-4172-9C3A-05352183D469}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F4C7B46C-B39F-4172-9C3A-05352183D469}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F4C7B46C-B39F-4172-9C3A-05352183D469}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F4C7B46C-B39F-4172-9C3A-05352183D469}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FD9833B9-3FB1-4612-BBB4-64F539DB0F8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FD9833B9-3FB1-4612-BBB4-64F539DB0F8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD9833B9-3FB1-4612-BBB4-64F539DB0F8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD9833B9-3FB1-4612-BBB4-64F539DB0F8B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C0235BA1-9198-42C0-92D8-7578E9B9D96B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C0235BA1-9198-42C0-92D8-7578E9B9D96B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C0235BA1-9198-42C0-92D8-7578E9B9D96B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C0235BA1-9198-42C0-92D8-7578E9B9D96B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B5939234-73ED-4DAD-A2C6-D61AA6DFB406}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B5939234-73ED-4DAD-A2C6-D61AA6DFB406}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B5939234-73ED-4DAD-A2C6-D61AA6DFB406}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B5939234-73ED-4DAD-A2C6-D61AA6DFB406}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{D546290B-E280-4D99-BA9C-0D364A0AFB54} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||
{DBB72F0F-755D-41CF-8FE2-F4B6AE214E91} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||
{93FB86DB-7D2A-46CE-AFD2-0B53E6A8CF69} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||
{EB784E77-FD42-46EC-9C8C-502B78962407} = {E0497F39-AFFB-4819-A116-E39E361915AB}
|
||||
{80588AF3-6B14-4D11-9DC4-1EF6453B54C9} = {FEB39027-9158-4DE2-997F-7ADAEF8188D0}
|
||||
{E9B21845-E51A-4B8C-AF0B-0C4CE16550BF} = {C30C98CD-3D69-4AE9-B680-0E0E6D8834C6}
|
||||
{348007AA-AB91-48B2-98DB-57D068E2C1AE} = {C30C98CD-3D69-4AE9-B680-0E0E6D8834C6}
|
||||
{F4C7B46C-B39F-4172-9C3A-05352183D469} = {93FB86DB-7D2A-46CE-AFD2-0B53E6A8CF69}
|
||||
{D546290B-E280-4D99-BA9C-0D364A0AFB54} = {93FB86DB-7D2A-46CE-AFD2-0B53E6A8CF69}
|
||||
{FD9833B9-3FB1-4612-BBB4-64F539DB0F8B} = {EB784E77-FD42-46EC-9C8C-502B78962407}
|
||||
{DBB72F0F-755D-41CF-8FE2-F4B6AE214E91} = {EB784E77-FD42-46EC-9C8C-502B78962407}
|
||||
{C0235BA1-9198-42C0-92D8-7578E9B9D96B} = {C30C98CD-3D69-4AE9-B680-0E0E6D8834C6}
|
||||
{B5939234-73ED-4DAD-A2C6-D61AA6DFB406} = {C30C98CD-3D69-4AE9-B680-0E0E6D8834C6}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
|
||||
namespace Microsoft.AspNet.RequestContainer
|
||||
{
|
||||
public static class ContainerExtensions
|
||||
{
|
||||
public static IBuilder UseMiddleware(this IBuilder builder, Type middleware, params object[] args)
|
||||
{
|
||||
// TODO: move this ext method someplace nice
|
||||
return builder.Use(next =>
|
||||
{
|
||||
//TODO: this should be MethodInfo.CreateDelegate for coreclr
|
||||
var typeActivator = builder.ServiceProvider.GetService<ITypeActivator>();
|
||||
var instance = typeActivator.CreateInstance(middleware, new[] { next }.Concat(args).ToArray());
|
||||
return (RequestDelegate)Delegate.CreateDelegate(typeof(RequestDelegate), instance, "Invoke");
|
||||
});
|
||||
}
|
||||
|
||||
public static IBuilder UseContainer(this IBuilder app)
|
||||
{
|
||||
return app.UseMiddleware(typeof(ContainerMiddleware));
|
||||
}
|
||||
|
||||
public static IBuilder UseContainer(this IBuilder app, IServiceProvider applicationServices)
|
||||
{
|
||||
app.ServiceProvider = applicationServices;
|
||||
|
||||
return app.UseMiddleware(typeof(ContainerMiddleware));
|
||||
}
|
||||
|
||||
public static IBuilder UseContainer(this IBuilder app, IEnumerable<IServiceDescriptor> applicationServices)
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.Add(applicationServices);
|
||||
app.ServiceProvider = serviceCollection.BuildServiceProvider(app.ServiceProvider);
|
||||
|
||||
return app.UseMiddleware(typeof(ContainerMiddleware));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
using System;
|
||||
#if NET45
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
#endif
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.RequestContainer
|
||||
{
|
||||
public class ContainerMiddleware
|
||||
{
|
||||
private const string LogicalDataKey = "__HttpContext_Current__";
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IServiceProvider _rootServiceProvider;
|
||||
private readonly IContextAccessor<HttpContext> _rootHttpContextAccessor;
|
||||
private readonly IServiceScopeFactory _rootServiceScopeFactory;
|
||||
|
||||
public ContainerMiddleware(
|
||||
RequestDelegate next,
|
||||
IServiceProvider rootServiceProvider,
|
||||
IContextAccessor<HttpContext> rootHttpContextAccessor,
|
||||
IServiceScopeFactory rootServiceScopeFactory)
|
||||
{
|
||||
if (rootServiceProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException("rootServiceProvider");
|
||||
}
|
||||
if (rootHttpContextAccessor == null)
|
||||
{
|
||||
throw new ArgumentNullException("rootHttpContextAccessor");
|
||||
}
|
||||
if (rootServiceScopeFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException("rootServiceScopeFactory");
|
||||
}
|
||||
|
||||
_next = next;
|
||||
_rootServiceProvider = rootServiceProvider;
|
||||
_rootServiceScopeFactory = rootServiceScopeFactory;
|
||||
_rootHttpContextAccessor = rootHttpContextAccessor;
|
||||
|
||||
_rootHttpContextAccessor.SetContextSource(AccessRootHttpContext, ExchangeRootHttpContext);
|
||||
}
|
||||
|
||||
private HttpContext AccessRootHttpContext()
|
||||
{
|
||||
#if NET45
|
||||
return CallContext.LogicalGetData(LogicalDataKey) as HttpContext;
|
||||
#else
|
||||
throw new NotImplementedException()
|
||||
#endif
|
||||
}
|
||||
|
||||
private HttpContext ExchangeRootHttpContext(HttpContext httpContext)
|
||||
{
|
||||
#if NET45
|
||||
var prior = CallContext.LogicalGetData(LogicalDataKey) as HttpContext;
|
||||
CallContext.LogicalSetData(LogicalDataKey, httpContext);
|
||||
return prior;
|
||||
#else
|
||||
throw new NotImplementedException()
|
||||
#endif
|
||||
}
|
||||
|
||||
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?");
|
||||
}
|
||||
|
||||
var priorApplicationServices = httpContext.ApplicationServices;
|
||||
var priorRequestServices = httpContext.RequestServices;
|
||||
|
||||
var appServiceProvider = _rootServiceProvider;
|
||||
var appServiceScopeFactory = _rootServiceScopeFactory;
|
||||
var appHttpContextAccessor = _rootHttpContextAccessor;
|
||||
|
||||
if (priorApplicationServices != null &&
|
||||
priorApplicationServices != appServiceProvider)
|
||||
{
|
||||
appServiceProvider = priorApplicationServices;
|
||||
appServiceScopeFactory = priorApplicationServices.GetService<IServiceScopeFactory>();
|
||||
appHttpContextAccessor = priorApplicationServices.GetService<IContextAccessor<HttpContext>>();
|
||||
}
|
||||
|
||||
using (var scope = appServiceScopeFactory.CreateScope())
|
||||
{
|
||||
var scopeServiceProvider = scope.ServiceProvider;
|
||||
var scopeHttpContextAccessor = scopeServiceProvider.GetService<IContextAccessor<HttpContext>>();
|
||||
|
||||
httpContext.ApplicationServices = appServiceProvider;
|
||||
httpContext.RequestServices = scopeServiceProvider;
|
||||
|
||||
var priorAppHttpContext = appHttpContextAccessor.ExchangeValue(httpContext);
|
||||
var priorScopeHttpContext = scopeHttpContextAccessor.ExchangeValue(httpContext);
|
||||
|
||||
try
|
||||
{
|
||||
await _next.Invoke(httpContext);
|
||||
}
|
||||
finally
|
||||
{
|
||||
scopeHttpContextAccessor.ExchangeValue(priorScopeHttpContext);
|
||||
appHttpContextAccessor.ExchangeValue(priorAppHttpContext);
|
||||
|
||||
httpContext.RequestServices = priorRequestServices;
|
||||
httpContext.ApplicationServices = priorApplicationServices;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"version": "0.1-alpha-*",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.DependencyInjection": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Abstractions": "0.1-alpha-*"
|
||||
},
|
||||
"configurations": {
|
||||
"net45": {},
|
||||
"k10": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.0.0",
|
||||
"System.ComponentModel": "4.0.0.0",
|
||||
"System.Diagnostics.Debug": "4.0.10.0",
|
||||
"System.Linq": "4.0.0.0",
|
||||
"System.Reflection": "4.0.10.0",
|
||||
"System.Runtime": "4.0.20.0",
|
||||
"System.Runtime.Extensions": "4.0.10.0",
|
||||
"System.Threading": "4.0.0.0",
|
||||
"System.Threading.Tasks": "4.0.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue