0
votes

I had originally set up DI with ninject for an asp.net web api 2 service with a single controller and everything was working correctly. Upon adding a second controller, ninject does not work for the new one. I'm getting the following error:

"An error occurred when trying to create a controller of type 'VstsController'. Make sure that the controller has a parameterless public constructor."

First controller (for which ninject works):

public class RepositoryController : ApiController
{
    private GitHubClient _client;

    public RepositoryController(IGitHubClientAuthenticated gitHubClientAuthenticated)
    {
        _client = gitHubClientAuthenticated.Client;
        _client.Credentials = gitHubClientAuthenticated.Credentials;
    }

Second controller:

    public class VstsController : ApiController
{
    private VssConnection _connection;
    public VstsController(IVssConnectionAuthenticated vssConnectionAuthenticated)
    {
        _connection = vssConnectionAuthenticated.VssConnection;
    }

Ninject config file:

private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IVssConnectionAuthenticated>().To<VssConnectionAuthenticated>();
        kernel.Bind<IGitHubClientAuthenticated>().To<GitHubClientAuthenticated>();
        kernel.Bind<IAuthenticationHelper>().To<AuthenticationHelper>();

    }    

Do I need to tweak anything if I want to keep adding controllers? Couldn't find any documentation on this. Thanks in advance

EDIT: Including ninject set up code as well as VssAuthenticated + IvssAuthenticated:

namespace Dashboard.WebAPI.Models
{
public interface IVssConnectionAuthenticated
    {
    VssConnection VssConnection { get;  }
    Uri Uri { get; }
    }
}


namespace Dashboard.WebAPI.Models
{
public class VssConnectionAuthenticated: IVssConnectionAuthenticated
{
    public VssConnection VssConnection { get; private set; }
    public Uri Uri { get; private set; }

    VssConnectionAuthenticated()
    {
        Uri = new Uri("uri");
        string vstsSecretUri = "vstssecreturi";
        GetKeyVaultSecret keyVaultSecretGetter = new GetKeyVaultSecret(new AuthenticationHelper(), vstsSecretUri);
        string keyVaultSecret = keyVaultSecretGetter.KeyVaultSecret;
        VssBasicCredential vssBasicCredential = new VssBasicCredential(string.Empty, keyVaultSecret); 
        VssConnection = new VssConnection(Uri, vssBasicCredential);
    }

Full Ninject Config File:

namespace Dashboard.WebAPI.App_Start
{
using System;
using System.Web;

using Microsoft.Web.Infrastructure.DynamicModuleHelper;

using Ninject;
using Ninject.Web.Common;
using System.Web.Http;
using Dashboard.WebAPI.Models;

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

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage the application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    /// <summary>
    /// Load modules and register services 
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IVssConnectionAuthenticated>().To<VssConnectionAuthenticated>();
        kernel.Bind<IGitHubClientAuthenticated>().To<GitHubClientAuthenticated>();
        kernel.Bind<IAuthenticationHelper>().To<AuthenticationHelper>();

    }        
}

}

Registering Ninject as Dependency Resolver:

namespace Dashboard.WebAPI.App_Start
{
public class NinjectDependencyScope : IDependencyScope
{
    IResolutionRoot resolver;

    public NinjectDependencyScope(IResolutionRoot resolver)
    {
        this.resolver = resolver;
    }

    public object GetService(Type serviceType)
    {
        if (resolver == null)
            throw new ObjectDisposedException("this", "This scope has been disposed");
        return resolver.TryGet(serviceType);
    }

    public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
    {
        if (resolver == null)
            throw new ObjectDisposedException("this", "This scope has been disposed");
        return resolver.GetAll(serviceType);
    }

    public void Dispose()
    {
        IDisposable disposable = resolver as IDisposable;
        if (disposable != null)
            disposable.Dispose();
        resolver = null;
    }
}
public class NinjectDependencyResolver: NinjectDependencyScope, IDependencyResolver
{
    IKernel kernel;

    public NinjectDependencyResolver(IKernel kernel) : base(kernel)
    {
        this.kernel = kernel;
    }

    public IDependencyScope BeginScope()
    {
        return new NinjectDependencyScope(kernel.BeginBlock());
    }
}

}

1
Did you specifically register RepositoryController anywhere? Are both classes in the same namespace?mason
Looks okay, but could you pls check VssConnectionAuthenticated file once again?Rakesh Burbure
Please show the startup code used to register Ninject with MVC and/or the Ninject-specific packages you have installed.NightOwl888
Might be an issue with VssConnectionAuthenticated for which Ninject is not able to resolve dependenciesjbl
@mason Both classes are in the same namespace. I did not register RepositoryController anywhere. All that is registered is under RegisteredServices(). @Rakesh@NightOwl I have edited the original question to include VssConnectionAuthenticated and the Ninject config files. The problem lies with ninject not being able to resolve the dependency in the constructor. If remove IVssConnectionAuthenticated as a dependency, everything works fine.sgonzalez

1 Answers

1
votes

In case anyone else runs into this problem- The problem was in VssConnectionAuthenticated: The constructor needs to be public.