How to configure Autofac and SignalR in a MVC 5 application

蹲街弑〆低调 提交于 2019-12-01 21:28:36
radu-matei

You should tell SignalR explicitly to use the AutofacDependencyResolver when you are mapping it. I assume that you know that in your Startup class you have to call app.MapSignalR();

When you are mapping it, you should tell it to use the custom dependency resolver (the AutofacDependencyResolver).

Here's how I do it:

var resolver = new AutofacDependencyResolver(container);

app.MapSignalR(new HubConfiguration
{
    Resolver = resolver
});

This way, you are telling SignalR directly which dependency resolver to use.

I have a GitHub repo for SignalR Dependency Injection, but it's not configured to use MVC. Still, I think it will give you a hint in how to create your configuration.

Note: If you are using the OWIN Middleware, be sure not to use the GlobalHost static property AT ALL since it will have massive inconsistencies.

A common error in OWIN integration is use of the GlobalHost. In OWIN you create the configuration from scratch. You should not reference GlobalHost anywhere when using the OWIN integration.

Again, check the repo I gave you to see how to do this.

Hope this helps:) Best of luck!

Andrii

I ended up with this (pay attention to comments):

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);

        IContainer container = AutofacConfig(app);
        app.UseAutofacMiddleware(container);
        app.UseAutofacMvc();
        DependencyResolver.SetResolver(new Autofac.Integration.Mvc.AutofacDependencyResolver(container));
        GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
        app.UseAutofacWebApi(GlobalConfiguration.Configuration);

        var hubConfiguration = new Microsoft.AspNet.SignalR.HubConfiguration()
        {
            // Resolve presolver from container
            Resolver = container.Resolve<Microsoft.AspNet.SignalR.IDependencyResolver>(),
        };
        app.MapSignalR(hubConfiguration);

        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

_

private static IContainer AutofacConfig(IAppBuilder app)
{
    var builder = new ContainerBuilder();

    RegisterSignalR(builder);

    return builder.Build();
}

_

private static void RegisterSignalR(ContainerBuilder builder)
{
    // Register Autofac resolver into container to be set into HubConfiguration later
    builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>()
           .As<Microsoft.AspNet.SignalR.IDependencyResolver>()
           .SingleInstance();

    // Register ConnectionManager as IConnectionManager so that you can get
    // hub context via IConnectionManager injected to your service
    builder.RegisterType<Microsoft.AspNet.SignalR.Infrastructure.ConnectionManager>()
           .As<Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager>()
           .SingleInstance();

    // Register hubs one by one
    builder.RegisterType<MessageNotificationsHub>().ExternallyOwned();
    builder.RegisterType<SystemNotificationsHub>().ExternallyOwned();
}

Thanks to @Nathan and his answer (originally found here) and logical thinking to figure out to register ConnectionManager as IConnectionManager

Install nuget package Autofac.SignalR, for example:

<package id="Autofac.SignalR" version="3.0.2" targetFramework="net471" />

Register your hubs

// during creation of the IContainer, register signalr hubs automatically
var executingAssembly = Assembly.GetExecutingAssembly();
builder.RegisterHubs(executingAssembly);

// alternatively register hubs individually
// ExternallyOwned() ensures SignalR is allowed to control disposal of the hubs rather than Autofac.
builder.RegisterType<NotificationHub>().ExternallyOwned();

Set signalr service locator

// replace the Signalr dependency resolver once your IContainer 'container' is ready
GlobalHost.DependencyResolver = new AutofacDependencyResolver(container);

// or this can alternatively be set in the HubConfiguration instance when using OWIN IAppBuilder map.RunSignalR(hubConfiguration);
var hubConfiguration = new HubConfiguration
{
    Resolver = new AutofacDependencyResolver(container),
    //...
}

For more information:

https://autofaccn.readthedocs.io/en/latest/integration/signalr.html

https://docs.microsoft.com/en-us/aspnet/signalr/overview/advanced/dependency-injection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!