将 SignalR 的 ITransportHeartbeat 添加到 Autofac
Posted
技术标签:
【中文标题】将 SignalR 的 ITransportHeartbeat 添加到 Autofac【英文标题】:Add SignalR's ITransportHeartbeat to Autofac 【发布时间】:2020-09-01 04:05:07 【问题描述】:我正在尝试使用 Autofac 为我的 ASP.NET MVC 5 应用程序创建一个 ITransportHeartbeat 接口实例,以跟踪所有连接的用户。我使用ITransportHeartbeat
接口来确定用户的连接是否仍处于活动状态。为此,我需要使用 Autofac 为应用程序创建一个 SignalR 集线器实例。
挑战:当我运行应用程序时,它永远不会遇到 SignalR 集线器中被覆盖的 OnConnected()
、OnReconnected()
或 OnDisconnected()
。但是,客户端的hub.start()
被命中,我在页面加载时看到Hub Started
消息:
$.connection.hub.start().done(function ()
console.log("Hub Started");
);
如果我向集线器添加一个无参数构造函数,它确实会命中它们,但是ITransportHeartbeat
接口为空,这破坏了将接口注入集线器的意义。
我参考了以下内容寻求帮助:
https://***.com/a/49214891/177416 https://autofaccn.readthedocs.io/en/latest/integration/signalr.html https://***.com/a/36476106/177416 https://***.com/a/21126852/177416这里是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);
这是其他集线器的派生集线器:
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...
这是从基础集线器继承的集线器之一:
[HubName("MyHub")]
public class MyHub : MonitoringHubBase
public MyHub(ITransportHeartbeat heartbeat) : base(heartbeat)
public MyHub()
【问题讨论】:
【参考方案1】:找到了解决办法!从集线器中删除了无参数 c'tor 并将Startup.cs
修改为此;希望这可以帮助下一个为此苦苦挣扎的人:
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);
在本文的帮助下:https://kwilson.io/blog/get-your-web-api-playing-nicely-with-signalr-on-owin-with-autofac/
【讨论】:
以上是关于将 SignalR 的 ITransportHeartbeat 添加到 Autofac的主要内容,如果未能解决你的问题,请参考以下文章
.net core 3.0 Signalr - 05 使用jwt将用户跟signalr关联
.net core 3.0 Signalr - 05 使用jwt将用户跟signalr关联