Well, that's a terrible way of doing it!
Don't build the service container in your controller's constructor. Instead, build it once, when the app starts, and use constructor injection to inject your dependencies into your controller.
You've tagged this as WebAPI2, so I'm assuming you're still using an older .NET Framework-based API project. To integrate that with the MS DI framework, you'll need a couple of classes:
public sealed class DependencyScope : IDependencyScope
{
private readonly IServiceScope _scope;
public DependencyScope(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);
}
public sealed class DependencyResolver : IDependencyResolver
{
private readonly IServiceProvider _serviceProvider;
public DependencyResolver(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void Dispose()
{
if (_serviceProvider is IDisposable disposable)
{
disposable.Dispose();
}
}
public object GetService(Type serviceType) => _serviceProvider.GetService(serviceType);
public IEnumerable<object> GetServices(Type serviceType) => _serviceProvider.GetServices(serviceType);
public IDependencyScope BeginScope()
{
var scope = _serviceProvider.CreateScope();
return new DependencyScope(scope);
}
}
public static class Registration
{
public static void RegisterApiDependencyInjection(this IServiceProvider rootServiceProvider, HttpConfiguration configuration)
{
configuration.DependencyResolver = new DependencyResolver(rootServiceProvider);
}
}
Use something like
Scrutor[
^] to automatically register your API controllers in the service collection:
public static IServiceCollection AddApiControllers(this IServiceCollection services, Func<ITypeSourceSelector, IImplementationTypeSelector> assemblySelector)
{
services.Scan(scan => assemblySelector(scan).AddClasses(classes => classes.AssignableTo<ApiController>()).AsSelf().WithScopedLifetime());
return services;
}
In your project, set up a class to initialize the DI container:
public static class DependencyConfig
{
public static void Register()
{
var services = new ServiceCollection();
ConfigureServices(services);
var provider = services.BuildServiceProvider(true);
provider.RegisterApiDependencyInjection(GlobalConfiguration.Configuration);
}
private static void ConfigureServices([NotNull] IServiceCollection services)
{
services.AddApiControllers(scan => scan.FromAssemblyOf<WebApiApplication>());
services.AddScoped<ICustomer_BLL, Customer_BLL>();
... add other services here ...
}
}
Call that from your
global.asac
startup:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
DependencyConfig.Register();
... other startup code here ...
}
}
Then inject your dependencies into the controllers:
public class HomeController : ApiController
{
private readonly ICustomer_BLL _Customer_BLL;
public HomeController(ICustomer_BLL customerBLL)
{
_Customer_BLL = customerBLL;
}
NB: Your
DbContext
instances should be registered with a
scoped lifetime, not singleton. You want a new instance per request, otherwise you'll have horrendous problems.
Since your customer BLL class almost certainly depends on a
DbContext
, then that should be registered as scoped as well.