Reputation: 6417
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
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
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
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