SignalR, WebAPI and MVC sharing the same dependency resolver kernel

对着背影说爱祢 提交于 2019-12-06 03:54:10

In order keep this 3 things working.. you should check these references out:

  1. Web API + Ninject http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api/
  2. SignalR + Ninject https://github.com/SignalR/SignalR/wiki/Extensibility (last part: When using ASP.NET MVC, configure SignalR first, then ASP.NET MVC)

For the second one, I refactored a little bit, since I need the kernel for SignalR Dependency Resolver

// Route SignalR.
GlobalHost.DependencyResolver = NinjectWebCommon.GetSignalrResolver();
RouteTable.Routes.MapHubs();

I defined GetSignalrResolver inside of NinjectWebCommon like this:

public static Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver GetSignalrResolver()
{
    return new Microsoft.AspNet.SignalR.Ninject.NinjectDependencyResolver(bootstrapper.Kernel);
}

Note: There are 2 different DependencyResolver: one for Web API (1) assigned to GlobalConfiguration.Configuration.DependencyResolver and the other for SignalR (2) assigned to GlobalHost.DependencyResolver

vtortola

I found the answer in another post: Singleton Scope binding not working as intended

Rather than binding as a singleton, "ToConstant" must be used:

var binding = Bind<MustBeSingleton>().ToConstant(new MustBeSingleton());

I have created a simple demo project with ASP.NET MVC, WebAPI and SignalR using the same dependency injection context.

https://drive.google.com/file/d/0B52OsuSSsroNX0I5aWFFb1VrRm8/edit?usp=sharing

The web app, contains a single page that shows the AppDomain and GetHashCode of an object that is supposed to be unique across the three frameworks, giving a result similar to:

Dependency Test

Framework   IMySingletonService instance
MVC         AppDomainId:2 / HashCode:5109846
WebAPI      AppDomainId:2 / HashCode:5109846
SignalR     AppDomainId:2 / HashCode:5109846

Other problem was, that Ninject was disposing my singleton because was IDisposable. I don't really understand why this happens, but that is another war.

Cheers.

in order to use a dependency resolver for both WebApi and SignalR you need to implement a class that looks like this:

    public class NinjectDependencyResolver : Microsoft.AspNet.SignalR.DefaultDependencyResolver,
    System.Web.Http.Dependencies.IDependencyResolver
{
    public readonly IKernel Kernel;

    public NinjectDependencyResolver(string moduleFilePattern)
        : base()
    {
        Kernel = new StandardKernel();
        Kernel.Load(moduleFilePattern);

    }
    public override object GetService(Type serviceType)
    {
        var service = Kernel.TryGet(serviceType) ?? base.GetService(serviceType);
        return service;
    }

    public override IEnumerable<object> GetServices(Type serviceType)
    {
        IEnumerable<object> services = Kernel.GetAll(serviceType).ToList();
        if (services.IsEmpty())
        {
            services = base.GetServices(serviceType) ?? services;
        }
        return services;
    }

    public System.Web.Http.Dependencies.IDependencyScope BeginScope()
    {
        return this;
    }

    public void Dispose()
    { }
}

then in your startup class you should register NinjectDependencyResolver for both WebApi and SignalR, like this:

public void Configuration(IAppBuilder app)
{
    var dependencyResolver = new NinjectDependencyResolver("*.dll");

    var httpConfiguration = new HttpConfiguration();
    httpConfiguration.DependencyResolver = dependencyResolver;
    app.UseWebApi(httpConfiguration);

    var hubConfig = new HubConfiguration { Resolver = dependencyResolver };
    app.MapSignalR(hubConfig);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!