I'm trying to inject an HttpContextBase
in my SignalR hub:
public class EventHub : Hub, IDisconnect
{
private readonly HttpContextBase _httpContextBase;
public EventHub(HttpContextBase httpContextBase)
{
_httpContextBase = httpContextBase;
}
[...]
}
The registration code looks like this:
private static void InitAutofac()
{
var builder = new ContainerBuilder();
var assembly = typeof (MvcApplication).Assembly;
builder.RegisterControllers(assembly).PropertiesAutowired();
builder.RegisterModule(new AutofacWebTypesModule());
builder.RegisterFilterProvider();
builder.RegisterAssemblyTypes(assembly)
.Where(InterfaceBasedInjectedClasses())
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(assembly)
.Where(InterfaceLessInjectedClasses())
.InstancePerLifetimeScope();
builder.RegisterType<SurvivalContainer>().InstancePerLifetimeScope();
builder.RegisterType<EventHub>().InstancePerLifetimeScope();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalHost.DependencyResolver = new SignalR.Autofac.AutofacDependencyResolver(container);
RouteTable.Routes.MapHubs();
}
And the error I'm getting is:
[DependencyResolutionException: No scope with a Tag matching 'httpRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being reqested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.]
Stacktrace:
Autofac.Core.Lifetime.MatchingScopeLifetime.FindScope(ISharingLifetimeScope mostNestedVisibleScope) +160
Autofac.Core.Resolving.InstanceLookup..ctor(IComponentRegistration registration, IResolveOperation context, ISharingLifetimeScope mostNestedVisibleScope, IEnumerable`1 parameters) +57
Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) +102
Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) +64
Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) +164
Autofac.Core.Container.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) +14
Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance) +70
Autofac.ResolutionExtensions.TryResolve(IComponentContext context, Type serviceType, Object& instance) +70
SignalR.Autofac.AutofacDependencyResolver.GetService(Type serviceType) in D:\etc\Dev\SignalR.Autofac\AutofacDependencyResolver.cs:30
SignalR.Hubs.DefaultHubActivator.Create(HubDescriptor descriptor) +60
SignalR.Hubs.DefaultHubManager.ResolveHub(String hubName) +27
SignalR.Hubs.HubDispatcher.CreateHub(IRequest request, HubDescriptor descriptor, String connectionId, TrackingDictionary state, Boolean throwIfFailedToCreate) +445
SignalR.Hubs.HubDispatcher.OnReceivedAsync(IRequest request, String connectionId, String data) +246
SignalR.<>c__DisplayClass6.<ProcessRequestAsync>b__4(String data) +29
SignalR.Transports.ForeverTransport.ProcessSendRequest() +63
SignalR.Transports.ForeverTransport.ProcessRequestCore(ITransportConnection connection) +70
SignalR.Transports.ForeverTransport.ProcessRequest(ITransportConnection connection) +5
SignalR.PersistentConnection.ProcessRequestAsync(HostContext context) +560
SignalR.Hubs.HubDispatcher.ProcessRequestAsync(HostContext context) +120
SignalR.Hosting.AspNet.AspNetHandler.ProcessRequestAsync(HttpContextBase context) +422 SignalR.Hosting.AspNet.HttpTaskAsyncHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +68
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
I'm just getting started with autofac and SignalR and I find myself a little stuck. None of the related topics on SO helped. Any idea on what I'm doing wrong?
The problem is this line:
The exception message indicates that, during resolution, something is trying to be resolved from a lifetime scope tagged
httpRequest
. You get registrations like this in Autofac when you register somethingInstancePerHttpRequest()
:If you look at the source of the
AutofacWebTypesModule
it registers the web abstractions (likeHttpContextBase
, the thing you're looking for) asInstancePerHttpRequest
.Further, if you look at the way the
Autofac.Integration.Mvc.AutofacDependencyResolver
works, whenever you resolve a type during a request, it creates a new, nested, named lifetime scope tagged withhttpRequest
. This allows you to have that magicInstancePerHttpRequest
.Under the assumption the
SignalR.Autofac
library you're using is the one here, which is also the one on NuGet), looking in theSignalR.Autofac.AutofacDependencyResolver
, no such nested/named lifetime scope is being created for service resolution.Thus, when Autofac tries to resolve the
HttpContextBase
dependency, it can't find thathttpRequest
tagged scope (because it doesn't exist) and issues the error you're seeing.There is no simple answer for this. The nested
httpRequest
scope is actually important because it basically can't exist outside of a real web request. It makes it "safe" - you can't get anHttpContextBase
if there's no web context (say, at application startup).If you need to inject an
HttpContextBase
and you're sure that yourEventHub
will only live for one web request and that's it (I'm no SignalR guy, so bear with me), it means you either need to:Without actually doing the work and testing it out myself, I can't really provide specific guidance on how to accomplish that. This exercise is left to the reader.