SignalR Dependency Resolver no funciona desde Javascript Hubs

Recientemente actualicé a la nueva versión de la excelente biblioteca SignalR y moví toda mi Inyección de dependencia de StructureMap a Ninject, ya que Ninject parecía tener mejor soporte.

Tengo la inyección de dependencia funcionando bien para las notificaciones del lado del servidor usando la "Transmisión a través de un concentrador desde fuera de un concentrador" que se describe aquí: https://github.com/SignalR/SignalR/wiki/Hubs.

El problema que tengo es que todos los mensajes de SignalR que se originan en el centro de Javascript no parecen estar activando la inyección de dependencia.

También estoy usando MVC4 WebAPI, que también requiere un poco de calzado para que funcione la inyección de dependencia.

Aquí está mi centro:

public class PresenceHub : Hub, IPresenceHub
{
    private readonly IUserRepository _userRepository;
    private readonly IFormsAuthenticationProvider _formsAuthenticationProvider;

    public PresenceHub(IFormsAuthenticationProvider formsAuthenticationProvider, IUserRepository userRepository)
    {
        _userRepository = userRepository;
        _formsAuthenticationProvider = formsAuthenticationProvider;
    }

    public void PresenceChange(string presence)
    {
        var user = _userRepository.FindById(_formsAuthenticationProvider.GetUserId());
        var rosterEntry = Mapper.Map<User, RosterEntryDto>(user);
        rosterEntry.Presence = presence;
        Clients.updatePresence(rosterEntry);
    }
}

Aquí está mi Ninject Bootstrapper:

Namespace SLx.Web.App_Start
{
using System;
using System.Web;

using Microsoft.Web.Infrastructure.DynamicModuleHelper;

using Ninject;
using Ninject.Web.Common;

public static class NinjectWebCommon 
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        // SignalR Ninject Resolver
        GlobalHost.DependencyResolver = new SignalR.Ninject.NinjectDependencyResolver(kernel);

        // WebApi Ninject Resolver
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

        RegisterServices(kernel);
        return kernel;
    }


    private static void RegisterServices(IKernel kernel)
    {

    }        
}

Estoy notificando a los clientes en el lado del servidor a través de un PresenceProxy definido de la siguiente manera:

public class PresenceHubProxy : IPresenceHubProxy
{
    private readonly IHubContext _hubContext;

    public PresenceHubProxy()
    {
        _hubContext = GlobalHost.ConnectionManager.GetHubContext<PresenceHub>();
    }

    public void NotifyLogin(RosterEntryDto user)
    {
        _hubContext.Clients.updatePresence(user);
    }

    public void NotifyLogout(RosterEntryDto user)
    {
        _hubContext.Clients.updatePresence(user);
    }
}

El Proxy funciona bien, se inyecta en los Controladores o sus dependencias y puede enviar mensajes a los clientes.

Cuando los clientes intentan llamar a SignalR a través de Javascript, aparece el siguiente error:

No parameterless constructor defined for this object.

Parece que Ninject no se invoca porque las dependencias no se inyectan en el constructor. ¿Qué debo hacer para que la inyección de dependencia funcione también para las llamadas de Javascript?

Actualizar --

Siguiendo el consejo de DFowler, reemplacé el Resolver en PostApplicationStart. Depuración Puedo ver en la ventana Inmediato que SignalR.GlobalHost.Resolver es del tipo NinjectDependencyResolver pero aún no funciona. Obtengo el mismo error: no hay un constructor sin parámetros.

Luego eliminé la biblioteca NuGet NinjectDependencyResolver y agregué el archivo fuente a mi solución y lo estoy usando para fines de depuración. La depuración en GetService y GetServices muestra que nunca se llama a ningún método en NinjectDependencyResolver.

¿Algunas ideas?

preguntado el 12 de junio de 12 a las 18:06

2 Respuestas

El problema era que no había llamado a RouteTable.Routes.MapHubs:

GlobalHost.DependencyResolver = new SignalRNinjectResolver(NinjectWebCommon.Kernel);
RouteTable.Routes.MapHubs(new SignalRNinjectResolver(NinjectWebCommon.Kernel));

Respondido el 13 de junio de 12 a las 17:06

De los documentos https://github.com/SignalR/SignalR/wiki/Extensibility:

NOTA: NO anule la resolución global en PreApplicationStart, no funcionará o solo funcionará algunas veces. Hágalo en PostApplicationStart (usando WebActivator) o en Global.asax.

Respondido el 12 de junio de 12 a las 20:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.