[英]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.