Reputation: 61
Following the AutoFac documentation, I was able to use AutoFac in ASP.NET Core 3.0 Preview 3. ASP.NET Core 3.0 Preview 4 and ASP.NET Core 3.0 Preview 5 introduced breaking changes and AutoFac no longer works. My controller methods return runtime errors.
The differences between ASP.NET Core 3.0 Preview 3 and ASP.NET Core 3.0 Preview 5 in my code is as follows:
IWebHostBuilder -> IHostBuilder
CreateWebHostBuilder -> CreateHostBuilder
WebHost.CreateDefaultBuilder(args) -> Host.CreateDefaultBuilder(args)
public IServiceProvider ConfigureServices(IServiceCollection services)
to
public void ConfigureServices(IServiceCollection services)
System.AggregateException
HResult=0x80131500
Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: API.Controllers.CityController Lifetime: Transient ImplementationType: CityController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'CityController'.) (Error while validating the service descriptor 'ServiceType: LocationController Lifetime: Transient ImplementationType: LocationController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'LocationController'.) (Error while validating the service descriptor 'ServiceType: PersonController Lifetime: Transient ImplementationType: PersonController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'PersonController'.) (Error while validating the service descriptor 'ServiceType: SchoolController Lifetime: Transient ImplementationType: SchoolController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'SchoolController'.) (Error while validating the service descriptor 'ServiceType: TestParentController Lifetime: Transient ImplementationType: TestParentController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'TestParentController'.) (Error while validating the service descriptor 'ServiceType: TypeController Lifetime: Transient ImplementationType: TypeController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'TypeController'.)
Source=Microsoft.Extensions.DependencyInjection
StackTrace:
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable`1 serviceDescriptors, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
at Microsoft.Extensions.Hosting.HostBuilder.Build()
at API.Program.Main(String[] args) in C:\Projects\FirstResponse\API\Program.cs:line 13
Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: CityController Lifetime: Transient ImplementationType: CityController': Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'CityController'.
Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 'IUnitOfWork' while attempting to activate 'CityController'.
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, builder) =>
{
builder.ClearProviders();
builder.SetMinimumLevel(LogLevel.Trace);
builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
builder.AddConsole();
builder.AddDebug();
})
.UseNLog();
});
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services
.AddCustomOptions(Configuration)
.AddCors()
.AddJwtAuthentication()
.AddHttpClients()
.AddCustomMVC()
.AddIIS()
.AddCaching()
.AddCustomDbContext(Configuration, Environment)
.AddSwagger()
.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies())
.AddHealthChecksUI();
var serviceProvider = services.BuildServiceProvider();
_appSettings = serviceProvider.GetService<IOptionsSnapshot<AppSettings>>().Value;
var connectionString = Configuration.GetConnectionString(nameof(FirstResponseContext));
// Create a Autofac container builder
var builder = new ContainerBuilder();
// Read service collection to Autofac
builder.Populate(services);
// Use and configure Autofac
builder.RegisterModule(new MediatorModule());
builder.RegisterModule(new ApplicationModule(connectionString));
// build the Autofac container
ApplicationContainer = builder.Build();
// creating the IServiceProvider out of the Autofac container
//return new AutofacServiceProvider(ApplicationContainer);
}
ApplicationModule.cs
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
builder.RegisterType<ModelValidationAttribute>().InstancePerLifetimeScope();
builder.RegisterType<ETagCache>().InstancePerLifetimeScope();
builder.RegisterType<FirstResponseContext>().As<DbContext>().As<IUnitOfWork>().InstancePerLifetimeScope();
}
Upvotes: 6
Views: 9180
Reputation: 247008
A few changes would need to be done to conform to the new syntax
You need to plug in the service provider factory for AutoFac
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) //<--NOTE THIS
.ConfigureWebHostDefaults(webBuilder => {
webBuilder
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, builder) => {
builder.ClearProviders();
builder.SetMinimumLevel(LogLevel.Trace);
builder.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
builder.AddConsole();
builder.AddDebug();
})
.UseNLog();
});
Then in the ConfigureContainer
method of your Startup
class, register things directly into an Autofac ContainerBuilder
.
public IConfigurationRoot Configuration { get; private set; }
public void ConfigureServices(IServiceCollection services) {
services
.AddCustomOptions(Configuration)
.AddCors()
.AddJwtAuthentication()
.AddHttpClients()
.AddCustomMVC()
.AddIIS()
.AddCaching()
.AddCustomDbContext(Configuration, Environment)
.AddSwagger()
.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies())
.AddHealthChecksUI();
}
public void ConfigureContainer(ContainerBuilder builder) {
var connectionString = Configuration.GetConnectionString(nameof(FirstResponseContext));
// Use and configure Autofac
builder.RegisterModule(new MediatorModule());
builder.RegisterModule(new ApplicationModule(connectionString));
}
The IServiceProvider
will automatically be created for you, so there’s nothing you have to do but register things.
Some of this was taken directly from Autofac documentation for Asp.Net Core
Upvotes: 9