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:
builder.RegisterModule(new AutofacWebTypesModule());
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 something InstancePerHttpRequest()
:
// These two are roughly equivalent:
builder.RegisterType<SomeType>().InstancePerHttpRequest();
builder.RegisterType<SomeType>().InstancePerMatchingLifetimeScope("AutofacWebRequest");
If you look at the source of the AutofacWebTypesModule
it registers the web abstractions (like HttpContextBase
, the thing you're looking for) as InstancePerHttpRequest
.
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 with httpRequest
. This allows you to have that magic InstancePerHttpRequest
.
Under the assumption the SignalR.Autofac
library you're using is the one here, which is also the one on NuGet), looking in the SignalR.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 that httpRequest
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 an HttpContextBase
if there's no web context (say, at application startup).
If you need to inject an HttpContextBase
and you're sure that your EventHub
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With