Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting dependencies for SignalR Hubs using autofac in in MVC 5 application

I'm trying to bring SignalR 2 into an existing project in which all dependency injection is performed using autofac and all dependency configuration is performed in Global.asax. I found the Autofac.SignalR package for using SignalR with autofac and its accompanying documentation.

I followed the example in the provided documentation and followed the suggestion of using the RegisterHubs function rather than defining my individual hub dependencies.

Unfortunately my Hub class gets the following run-time error when trying to resolve a dependency from the lifetimeScope

Autofac.Core.DependencyResolutionException was unhandled by user code
HResult=-2146233088
Message=No scope with a Tag matching 'AutofacWebRequest' is
visible from the scope in which instance was requested.
This generally indicates that a component registered as per-HTTP
request is being requested 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.

I haven't been able to get DependencyResolver.Current or ILifeTimeScopeProvider to work for me.

My dependency config is as follows

var builder = new ContainerBuilder();
    .RegisterControllers(typeof (MvcApplication).Assembly);
    .RegisterHubs(Assembly.GetExecutingAssembly());
    ...
var container = builder.Build();

// Set dependency resolver for MVC
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

// Set dependency resolver for Web API
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);

// Set the dependency resolver for SignalR
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

var signalRDependencyResolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(container);
GlobalHost.DependencyResolver = signalRDependencyResolver;

I also set up my hub class according to the example:

public class BaseHub : Hub
{
    protected readonly ILifetimeScope _hubLifetimeScope;
    private static IUserSignalRConnectionRepository _userSignalRConnectionRepository;

    public BaseHub(ILifetimeScope lifetimeScope) : base()
    {
        _hubLifetimeScope = lifetimeScope.BeginLifetimeScope();

        _userSignalRConnectionRepository = _hubLifetimeScope.Resolve<IUserSignalRConnectionRepository>();
    }

    protected override void Dispose(bool disposing)
    {
        // Dipose the hub lifetime scope when the hub is disposed.
        if (disposing && _hubLifetimeScope != null)
            _hubLifetimeScope.Dispose();

        base.Dispose(disposing);
    }
}

The exception occurs in the cub class on the line

_userSignalRConnectionRepository = _hubLifetimeScope.Resolve<IUserSignalRConnectionRepository>();
like image 480
B Sharp Avatar asked Mar 04 '14 22:03

B Sharp


1 Answers

You should include the code where you are registering your IUserSignalRConnectionRepository.

The error message seems to indicate that this dependency was registered using InstancePerHttpRequest() which equivalent to InstancePerMatchingLifetimeScope("AutofacWebRequest"). This scope is created automatically for you in the case of MVC requests, but not for SignalR requests (which is probably a good thing since they can last indefinitely).

You can probably work around this by calling lifetimeScope.BeginLifetimeScope("AutofacWebRequest");. instead of lifetimeScope.BeginLifetimeScope(); in your Hub constructor.

Alternatively, you could register IUserSignalRConnectionRepository using InstancePerDependency() (which is the default) or SingleInstance() instead of InstancePerHttpRequest().

like image 173
halter73 Avatar answered Sep 23 '22 15:09

halter73