Kevin Bradshaw
Kevin Bradshaw

Reputation: 6417

Dependency injection breaks my WebApi Controller

I have an MVC project with makes use of the DI pattern in my controllers, using Unity to resolve my dependencies.

I recently introduced WebApi package and it is after introducing an annoying bug.

When I try to inject my service class into a web api controller I get the following error:

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

This is the code

public class TestController : ApiController
{
    private readonly IBrokerService _brokerAccessService;
    public TestController(IBrokerService brokerAccessService)
    {
        _brokerAccessService = brokerAccessService;
    }

    /// Controller methods here

}

I can add a paramaterless constructor like so and it works fine

        public TestController()
    {
        _brokerAccessService = new BrokerService(new BrokerRepository(new ForexRebatesNowEntities()));
    }

But that totally violates the DI pattern

I have this Service injected into other controllers (derived from MVCs 'BaseController' rather than the WebApi 'ApiController') and there are no issues

Is there a difference in the way MVC controllers and APi Controllers handle DI?

Upvotes: 2

Views: 1016

Answers (3)

AtLeastTheresToast
AtLeastTheresToast

Reputation: 387

For anyone that is using .NET 7 you are going to want to register your services in the Program.cs file. If you have a custom data context make sure you add it along with the out of the box application data context.

var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));


builder.Services.AddDbContext<CustomDbContextName>(options =>
    options.UseSqlServer(connectionString));

builder.Services.AddControllers();
builder.Services.AddTransient<INamedService, NamedService>();

Hope that helps, spent a few hours digging around for this.

Upvotes: 0

Muheeb
Muheeb

Reputation: 226

Did you set the dependency resolver on the DependencyResolver property of the global HttpConfiguration object?

public static void Register(HttpConfiguration config)
{
  var container = new UnityContainer();
  container.RegisterType<IBrokerService, BrokerService>(new              
                    HierarchicalLifetimeManager());;
  config.DependencyResolver = new UnityResolver(container);
}

Or

Create UnityConfig.cs in App_Start folder

    public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = new UnityContainer();

        // register all your components with the container here
        // it is NOT necessary to register your controllers

        // e.g. container.RegisterType<ITestService, TestService>();
        container.RegisterType<IBrokerService, BrokerService>();
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }
}

Then call this static method in Global.asax.cs

     protected void Application_Start()
    {
        //Register your unity configuration
        UnityConfig.RegisterComponents();            
    }

Upvotes: 0

mcbowes
mcbowes

Reputation: 798

It seems like your Dependency Resolver is not set for WebAPI. If you moved over from using a Controller to a WebApi controller, the DependencyResolver is different. For your regular MVC controller you may have been making a call similar to DependencyResolver.SetResolver() but the DI for WebApi controller needs to have its dependency Resolver set off of the HttpConfiguration, something like httpConfiguration.DependencyResolver =

For example, in some projects I use SimpleInjector (idea should be the same)-

MVC DI Config:

DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(mvcContainer));

WebAPI config:

httpConfiguration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(apiContainer);

As a side note- these calls are both in the same project where we have MVC controller and a WebApi in the same solution.

Upvotes: 1

Related Questions