简体   繁体   English

将 SignalR 的 ITransportHeartbeat 添加到 Autofac

[英]Add SignalR's ITransportHeartbeat to Autofac

I'm trying to use Autofac to have one instance of the ITransportHeartbeat interface for my ASP.NET MVC 5 app to track all connected users.我正在尝试使用 Autofac 为我的 ASP.NET MVC 5 应用程序创建一个ITransportHeartbeat接口实例来跟踪所有连接的用户。 I use the ITransportHeartbeat interface to determine if a user's connection is still active.我使用ITransportHeartbeat接口来确定用户的连接是否仍处于活动状态。 To do this, I need to have one instance of the SignalR hub for the app by using Autofac.为此,我需要使用 Autofac 为应用程序创建一个 SignalR 集线器实例。

The challenge: when I run the app, it never hits the overridden OnConnected() , OnReconnected() , or OnDisconnected() in the SignalR hub.挑战:当我运行应用程序时,它永远不会遇到 SignalR 集线器中被覆盖的OnConnected()OnReconnected()OnDisconnected() However, the client's hub.start() is hit and I see the Hub Started message when the page loads:但是,客户端的hub.start()被命中,当页面加载时我看到Hub Started消息:

$.connection.hub.start().done(function () {
    console.log("Hub Started");
});

If I add a parameterless constructor to the hub, it does hit them, but then the ITransportHeartbeat interface is null and that defeats the point of injecting the interface into the hub.如果我向集线器添加一个无参数的构造函数,它确实会命中它们,但是ITransportHeartbeat接口是 null,这破坏了将接口注入集线器的意义。

I've referenced the following for help:我参考了以下内容以寻求帮助:

Here is Startup.cs :这是Startup.cs

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

        var builder = new ContainerBuilder();
        var config = GlobalConfiguration.Configuration;

        builder.RegisterControllers(typeof(MvcApplication).Assembly)
            .InstancePerRequest();
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly())
            .InstancePerRequest();

        var signalRConfig = new HubConfiguration();
        builder.RegisterType<MonitoringHubBase>().ExternallyOwned();

        builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>()
            .As<Microsoft.AspNet.SignalR.IDependencyResolver>()
            .SingleInstance();
        builder.Register(context => 
            context.Resolve<Microsoft.AspNet.SignalR.IDependencyResolver>()
            .Resolve<IConnectionManager>()
            .GetHubContext<MonitoringHubBase, IMonitoringHubBase>())
            .ExternallyOwned();
        builder.RegisterType<Microsoft.AspNet.SignalR.Transports.TransportHeartbeat>()
            .As<Microsoft.AspNet.SignalR.Transports.ITransportHeartbeat>()
            .SingleInstance();

        var container = builder.Build();
        DependencyResolver.SetResolver(
            new Autofac.Integration.Mvc.AutofacDependencyResolver(container));

        signalRConfig.Resolver = container
            .Resolve<Microsoft.AspNet.SignalR.IDependencyResolver>();

        app.UseAutofacMiddleware(container);
        app.MapSignalR("/signalr", signalRConfig);

        config.DependencyResolver = 
            new AutofacWebApiDependencyResolver((IContainer)container);

        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

Here is the hub from which the other hubs derive:这是其他集线器从中派生的集线器:

public interface IMonitoringHubBase
{
    Task OnConnected();
    Task OnReconnected();
    Task OnDisconnected(bool stopCalled);
}

public abstract class MonitoringHubBase : Hub<IMonitoringHubBase>
{
    private ITransportHeartbeat Heartbeat { get; }

    public MonitoringHubBase(ITransportHeartbeat heartbeat)
    {
        Heartbeat = heartbeat;
    }

    public MonitoringHubBase()
    {
    }

    public override async Task OnConnected()
    {
        // Add connection to db...
    }

    public override async Task OnReconnected()
    {
        // Ensure connection is on db...
    }

    public override async Task OnDisconnected(bool stopCalled)
    {
        // Remove connection from db...
    }

    public async Task SomeMethod(int id)
    {
        // Heartbeat object used here...
    }
}

And here's one of the hubs that inherits from the base hub:这是从基础集线器继承的集线器之一:

[HubName("MyHub")]
public class MyHub : MonitoringHubBase
{
    public MyHub(ITransportHeartbeat heartbeat) : base(heartbeat)
    {
    }

    public MyHub()
    {   
    }
}

Found a solution!找到了解决办法! Removed the parameterless c'tor from the hub and modified Startup.cs to this;从集线器中删除了无参数 c'tor 并将Startup.cs修改为此; hope this helps the next person struggling with this:希望这可以帮助下一个为此苦苦挣扎的人:

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

        var builder = new ContainerBuilder();
        var config = new HttpConfiguration();

        builder.RegisterHubs(Assembly.GetExecutingAssembly());
        builder.RegisterControllers(typeof(MvcApplication).Assembly)
            .InstancePerRequest();
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly())
            .InstancePerRequest();
        builder.RegisterType<Microsoft.AspNet.SignalR.Transports.TransportHeartbeat>()
            .As<Microsoft.AspNet.SignalR.Transports.ITransportHeartbeat>()
            .SingleInstance();
        builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>()
            .As<Microsoft.AspNet.SignalR.IDependencyResolver>()
            .SingleInstance();

        var container = builder.Build();

        var signalRConfig = new HubConfiguration();
        signalRConfig.Resolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(container);

        app.UseAutofacMiddleware(container);

        DependencyResolver.SetResolver(new Autofac.Integration.Mvc.AutofacDependencyResolver(container));

        app.Map("/signalr", map =>
        {
            map.UseAutofacMiddleware(container);

            var hubConfiguration = new HubConfiguration
            {
                Resolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(container),
            };

            map.RunSignalR(hubConfiguration);
        });

        config.DependencyResolver = new AutofacWebApiDependencyResolver((IContainer)container);

        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

With help from this article: https://kwilson.io/blog/get-your-web-api-playing-nicely-with-signalr-on-owin-with-autofac/在本文的帮助下: https://kwilson.io/blog/get-your-web-api-playing-nicely-with-signalr-on-owin-with-autofac/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM