asp.net signalr autofac owin

asp.net - SignalR+Autofac+OWIN: ¿Por qué no funciona GlobalHost.ConnectionManager.GetHubContext?



(3)

Estoy tratando de usar OWIN, SignalR y Autofac en un solo proyecto.

Estoy configurando las cosas con respecto a signalR de la siguiente manera:

// Create the AutoFac container builder: var builder = new ContainerBuilder(); // ...[Register various other things in here]... // register signalR Hubs builder.RegisterHubs(Assembly.GetExecutingAssembly()); // Build the container: var container = builder.Build(); // Configure SignalR with the dependency resolver. app.MapSignalR(new HubConfiguration { Resolver = new AutofacDependencyResolver(container) });

Mi problema es que cuando uso la integración Autofac SignalR, ya no puedo obtener un SignalR Hub Context en el servidor (en un controlador webapi, por ejemplo) y, por lo tanto, no puedo enviar mensajes desde el servidor a los clientes conectados. Algo como lo siguiente es cómo hago esto cuando no estoy usando la integración Autofac signalR:

var hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>(); hubContext.Clients.All.notification("Test Message");

Pero esto no funciona cuando agrego Autofac a la mezcla: no recibo ningún mensaje de error y parece que obtengo un HubContext, pero las llamadas no parecen llegar a los clientes.

Si comento el uso del resolvedor de dependencias para signalR en la llamada a MapSignalR, la llamada a GetHubContext funciona de nuevo y los mensajes llegan a los clientes de signalR con éxito, pero, por supuesto, ya no puedo usar IoC en mis hubs. p.ej

// Configure SignalR with the dependency resolver. app.MapSignalR(new HubConfiguration { // Resolver = new AutofacDependencyResolver(container) });

¿Alguien puede decirme por qué el uso de AutofacDependencyResolver evita que GlobalHost.ConnectionManager.GetHubContext funcione correctamente?

NOTA: Otra cosa que he intentado es en lugar de usar GlobalHost.ConnectionManager.GetHubContext () Intenté inyectar un IConnectionManager en el controlador webapi desde el que deseo enviar un mensaje a los clientes, luego llamar a GetHubContext, pero Autofac no pudo resolver el IConnectionManager.

Encontré el siguiente artículo de Piotr Szmyd que aparentemente lo permite:

http://www.szmyd.com.pl/blog/wiring-signalr-with-autofac

pero esto parece estar basado en construcciones obsoletas de signalR, y aunque parece que hay un paquete nuget para ello aquí:

http://www.nuget.org/packages/SignalR.AutoFac/

También parece fuera de fecha.


Para ampliar la respuesta de Nathan, estoy usando algo similar con la línea clave que está

builder.RegisterHubs(Assembly.GetExecutingAssembly()).SingleInstance();

en Startup.cs.

La línea "SingleInstance ()" garantiza que solo se utilice una "instancia" del concentrador en toda la aplicación.

Luego, solo uso una inyección de dependencia directa en el constructor del controlador para obtener un puntero al concentrador.


Para una respuesta completa, con SignalR, Autofac y OWIN, hice lo siguiente:

// register IPersistantConnectionContext for access to SignalR connection // and IDependencyResolver to enable inection of the container into its // construction for the config object. var builder = new ContainerBuilder(); builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>() .As<IDependencyResolver>() .SingleInstance(); builder.Register((context, p) => context.Resolve<IDependencyResolver>() .Resolve<Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager>() .GetConnectionContext<SignalRConnection>()); // ... other registrations var container = builder.Build(); var signalrConfiguration = new ConnectionConfiguration { Resolver = container.Resolve<IDependencyResolver>(), }; app.UseAutofacMiddleware(container); app.MapSignalR<SignalRConnection>("/signalr", signalrConfiguration); // ... other middleware

En mis controladores, incluí un parámetro del tipo IPersistentConnectionContext y se inyecta la instancia correcta.

Estaba usando una conexión persistente, pero debería ser similar para los concentradores.


Si usa un sistema de resolución de dependencias personalizado con SignalR, ya no podrá usar GlobalHost menos que lo modifique:

GlobalHost.DependencyResolver = new AutofacDependencyResolver(container); IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>(); // A custom HubConfiguration is now unnecessary, since MapSignalR will // use the resolver from GlobalHost by default. app.MapSignalR();

Si no desea modificar GlobalHost, tendrá que resolver manualmente su IConnectionManager:

IDependencyResolver resolver = new AutofacDependencyResolver(container); IHubContext hubContext = resolver.Resolve<IConnectionManager>().GetHubContext<MyHub>(); app.MapSignalR(new HubConfiguration { Resolver = resolver });