Area error when using Autofac with SignalR

I am trying to inject an HttpContextBase into my SignalR hub:

 public class EventHub : Hub, IDisconnect { private readonly HttpContextBase _httpContextBase; public EventHub(HttpContextBase httpContextBase) { _httpContextBase = httpContextBase; } [...] } 

The registration code is as follows:

 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 get is:

[DependencyResolutionException: the absence of an area with matching tags "httpRequest" is visible from the area in which the instance was requested. This usually indicates that the component registered as for the HTTP request is requested by the SingleInstance () component (or a similar script.) As part of web integration, dependencies on DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime are always requested, never from the container by 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 starting out with autofac and SignalR, and I'm a little stuck. None of the related topics on SO helped. Any idea what I'm doing wrong?

+6
source share
1 answer

The problem is this line:

 builder.RegisterModule(new AutofacWebTypesModule()); 

An exception message indicates that something is trying to resolve something from the scope with the httpRequest tag httpRequest . You get a register like this in Autofac when you register something with InstancePerHttpRequest() :

 // These two are roughly equivalent: builder.RegisterType<SomeType>().InstancePerHttpRequest(); builder.RegisterType<SomeType>().InstancePerMatchingLifetimeScope("AutofacWebRequest"); 

If you look at the source of AutofacWebTypesModule , it registers network abstractions (e.g. HttpContextBase , what you are looking for) as InstancePerHttpRequest .

Also, if you look at how Autofac.Integration.Mvc.AutofacDependencyResolver works, whenever you enable a type during a query, it creates a new, nested named scope over time with the httpRequest tag. This allows you to have the magic of InstancePerHttpRequest .

Assuming that the SignalR.Autofac library you use is here, here , which is also the one on NuGet ), looking at SignalR.Autofac.AutofacDependencyResolver , no such nested / named lifetime is created to allow the service .

Thus, when Autofac tries to resolve the HttpContextBase dependency, it cannot detect this area with httpRequest tags (because it does not exist) and throws an error that you see.

There is no simple answer for this . The httpRequest nested scope httpRequest really important, because it basically cannot exist outside of a real web request. This makes it “safe” - you cannot get an HttpContextBase if there is no web context (say, when you start the application).

If you need to enter HttpContextBase , and you are sure that your EventHub will live for only one web request and that it (I am not a SignalR guy, so bear with me), this means that you either need:

  • Request a fix for this from the SignalR.Autofac project.
  • Implement your own SignalR.Autofac.AutofacDependencyResolver, which handles things like the MVC converter does.

Without performing the work itself and checking it, I cannot give concrete instructions on how to do this. This exercise is provided to the reader.

+5
source

Source: https://habr.com/ru/post/927263/


All Articles