ASP.NET Core Pitfalls – Returning a Custom Service Provider
This post is meant to replace https://weblogs.asp.net/ricardoperes/asp-net-core-pitfalls-returning-a-custom-service-provider-from-configureservices.
In pre-3.1 versions of ASP.NET Core, you could return your own service provider (AutoFac, Ninject, etc) by returning some IServiceProvider-implementing class from the ConfigureServices method. This is no longer supporting, and having code like this results in an NotSupportedException being thrown at startup:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
//something
return myCustomServiceProvider;
}
The way to do it from 3.1 was by registering a service provider factory at bootstrap, something like this:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new CustomServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
However, for more recent .NET versions that use WebApplication for bootstrap, replacing the service provider through UseServiceProviderFactory is like this:
var builder = WebApplication.CreateDefaultBuilder(args);
builder.Host.UseServiceProviderFactory<IServiceCollection>(static factory =>
{
return new CustomServiceProviderFactory(new ServiceProviderOptions { ValidateOnBuild = true, ValidateScopes = true });
});
However, because WebApplication internally instantiates and uses a DefaultServiceProviderFactory, it is not possible to use the custom one for all purposes.
A custom service provider factory must implement IServiceProviderFactory<T>, where T is normally IServiceCollection, for an example, you can see Autofac’s implementation: https://github.com/autofac/Autofac.Extensions.DependencyInjection/blob/develop/src/Autofac.Extensions.DependencyInjection/AutofacServiceProviderFactory.cs and https://github.com/autofac/Autofac.Extensions.DependencyInjection/blob/develop/src/Autofac.Extensions.DependencyInjection/AutofacChildLifetimeScopeServiceProviderFactory.cs.