Home > Net >  How to configure dependency injection for self hosted MVC 4 API controllers
How to configure dependency injection for self hosted MVC 4 API controllers

Time:09-17

After checking all the similar questions on SO, my issue persists so I'm opening a new question for it.

I have a unit test that references anther project that contains a MVC 4 ApiController which has a constructor for dependency injection.

public class DataController : ApiController
{
    public DataController(IRepository repository){}    
}

In my test, I'm using Microsoft.Extensions.DependencyInjection and have the following setup:

// Note: this redundant type access is necessary to load controllers from a different assembly,
// see https://stackoverflow.com/a/11758025/1468097
var type = typeof(DataController);

var services = new ServiceCollection().AddSingleton<IRepository>(new ImMemoryRepository());
var httpConfiguration = new HttpConfiguration
{ 
    DependencyResolver = new DependencyResolver(services.BuildServiceProvider()),
    IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always
};
httpConfiguration.Routes.MapHttpRoute("Default", "{controller}/{action}");
httpConfiguration.DependencyResolver = new DependencyResolver(services.BuildServiceProvider());
var httpServer = new HttpServer(httpConfiguration);
var client = new HttpClient(httpServer);
var response = await client.GetAsync("http://whatever/data/getdata?id=000");

and I have a fairly barebone implementation of the dependency resolver as nested private class inside the test class:

private class DependencyResolver : IDependencyResolver
{
    private readonly ServiceProvider _serviceProvider;

    public DependencyResolver(ServiceProvider serviceProvider) => _serviceProvider = serviceProvider;

    public void Dispose() => _serviceProvider.Dispose();

    public object GetService(Type serviceType) => _serviceProvider.GetService(serviceType);

    public IEnumerable<object> GetServices(Type serviceType) => _serviceProvider.GetServices(serviceType);

    public IDependencyScope BeginScope() => new Scope(_serviceProvider.CreateScope());

    private class Scope : IDependencyScope
    {
        private readonly IServiceScope _scope;

        public Scope(IServiceScope scope) => _scope = scope;

        public void Dispose() => _scope.Dispose();

        public object GetService(Type serviceType) => _scope.ServiceProvider.GetService(serviceType);

        public IEnumerable<object> GetServices(Type serviceType) => _scope.ServiceProvider.GetServices(serviceType);
    }
}

The response I get from the test is a 500 server error saying

Type 'Mvc.DataController' does not have a default constructor

It seems I'm doing what all the others are doing for dependency injection in MVC 4, even for this question that has a very similar symptom.

Am I missing something obvious here?

Update

I've tried NinjectResolver comes down to the same problem:

var kernel = new StandardKernel();
kernel.Bind<IRepository>().ToConstant(new InMemoryRepository());
var httpConfiguration = new HttpConfiguration
{
    DependencyResolver = new NinjectResolver(kernel)
};

CodePudding user response:

I figured this out.

The key is that you also need to add the controller you are hitting in your dependency configuration.

In my case, I just need to add:

var services = new ServiceCollection();

// This is what was missing.
services.AddTransient<DataController>();

Taken from here (although I'm not using OWIN at all): How to add Microsoft.Extensions.DependencyInjection to OWIN Self-Hosted WebApi

Another example using Autofac:

var builder = new ContainerBuilder();

// You need to register the assembly that contains your controller.
builder.RegisterApiControllers(typeof(DataController).Assembly);

Taken from here: Dependency injection not working with Owin self-hosted Web Api 2 and Autofac

  • Related