I'm trying to configure Autofac to play nice with my Web API/Oauth Identity project, but it does not seem to work. I keep getting the 'cannot resolve parameter ApplicationUserManager on constructor ....'
This is the service which doesn't get instantiated:
public class EmployeeService : Service<Employee>, IEmployeeService
{
private readonly ApplicationUserManager _userManager;
public EmployeeService(IUnitOfWork uow, ApplicationUserManager userManager)
: base(uow)
{
_userManager = userManager;
}
// .. other code
}
The ApplicationUserManager:
public class ApplicationUserManager : UserManager<Employee>
{
public ApplicationUserManager(IUserStore<Employee> store, IdentityFactoryOptions<ApplicationUserManager> options)
: base(store)
{
this.EmailService = new EmailService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
this.UserTokenProvider = new DataProtectorTokenProvider<Employee>(dataProtectionProvider.Create("ASP.NET Identity"))
{
//Code for email confirmation and reset password life time
TokenLifespan = TimeSpan.FromHours(6)
};
}
// UserValidator and PasswordValidator
// ...
}
}
And the autofac configuration:
public static void RegisterAutofac()
{
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterAssemblyTypes(typeof(IRepository<>).Assembly).AsClosedTypesOf(typeof(IRepository<>));
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces();
// Tried, doesn't work:
//builder.RegisterType<MyContext>();
//builder.RegisterType<UserStore<Employee>>().AsImplementedInterfaces();
//builder.RegisterType<ApplicationUserManager>().As<UserManager<Employee>>();
// Also doesn't work:
builder.RegisterInstance(new MyContext());
builder.RegisterType<UserStore<Employee>>().AsImplementedInterfaces().InstancePerRequest();
builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c =>
new IdentityFactoryOptions<ApplicationUserManager>()
{
DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ApplicationName")
});
builder.RegisterType<ApplicationUserManager>().As<UserManager<Employee>>().InstancePerRequest();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
The folllowing did work, but doesn't use DI:
public class EmployeeService : Service<Employee>, IEmployeeService
{
private readonly ApplicationUserManager _userManager;
public EmployeeService(IUnitOfWork uow)
: base(uow)
{
var store = new UserStore<Employee>(Uow.GetDbContext());
_userManager = new ApplicationUserManager(store);
}
}
Anyone knows what I'm doing wrong?
(Can provide more code if more information is needed)
EDIT
Exception message & stacktrace:
exceptionMessage: "None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type
'AngularMVC.Services.EmployeeService' can be invoked with the
available services and parameters: Cannot resolve parameter
'AngularMVC.DAL.ApplicationUserManager userManager' of constructor
'Void .ctor(AngularMVC.DAL.IUnitOfWork,
AngularMVC.DAL.ApplicationUserManager)'." exceptionType:
"Autofac.Core.DependencyResolutionException" stackTrace: " at
Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext
context, IEnumerable1 parameters) at
Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1
parameters) at Autofac.Core.Resolving.InstanceLookup.Execute() at
Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope
currentOperationScope, IComponentRegistration registration,
IEnumerable1 parameters) at
Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration
registration, IEnumerable1 parameters) at
Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass2.b__0()
at
Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
at
Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext
context, IEnumerable1 parameters) at
Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1
parameters) at Autofac.Core.Resolving.InstanceLookup.Execute() at
Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope
currentOperationScope, IComponentRegistration registration,
IEnumerable1 parameters) at
Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration
registration, IEnumerable1 parameters) at
Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration
registration, IEnumerable1 parameters) at
Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration
registration, IEnumerable1 parameters) at
Autofac.ResolutionExtensions.TryResolveService(IComponentContext
context, Service service, IEnumerable1 parameters, Object& instance)
at
Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext
context, Service service, IEnumerable1 parameters) at
Autofac.ResolutionExtensions.ResolveOptional(IComponentContext
context, Type serviceType, IEnumerable1 parameters) at
Autofac.ResolutionExtensions.ResolveOptional(IComponentContext
context, Type serviceType) at
Autofac.Integration.WebApi.AutofacWebApiDependencyScope.GetService(Type
serviceType) at
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage
request, Type controllerType, Func1& activator) at
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage
request, HttpControllerDescriptor controllerDescriptor, Type
controllerType)"
This is how I have registered ApplicationUserManager in Autofac, which works for all my applications.
builder.Register(c => HttpContext.Current.GetOwinContext().GetUserManager).As<ApplicationUserManager>();
This will say to Autofac that when I ask for an ApplicationUserManager, please get the UserManager from the OwinContext in my Current HttpContext.
This takes the logic and the dependecy on an OwinContext and HttpContext out of the classes, and makes the code much nicer to work with.
You can also do the same for an IAuthenticationManager, to remove your OwinContext dependency also with
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();
Related
I have a net.core 3.1 hosted service application. In this app, autofac is used as a DI container in addition to a standard container. I try to adding and use IMemoryCache as following:
In Program.cs
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(...)
...etc
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureServices((hostContext, services) =>
{
// Register configuration
services.AddMemoryCache();
// some another services
}
.ConfigureContainer<ContainerBuilder>(ConfigureContainer)
.UseConsoleLifetime();
ConfigureContainer is a method where some types are registered using autofac.
In my service I add memory cache dependency as following:
public class MyService: IMyService
{
private readonly IMemoryCache _memoryCache;
public MyService(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
}
But I get this exception when application was started:
Autofac.Core.DependencyResolutionException: An exception was thrown while activating λ:Microsoft.Extensions.Hosting.IHostedService[] -> MyNamespace.WorkerService -> MyNamespace.MyAnotherService -> MyNamespace.SomeAnotherService -> MyNamespace.MyService -> Microsoft.Extensions.Caching.Memory.MemoryCache.
---> Autofac.Core.DependencyResolutionException: An exception was thrown while invoking the constructor 'Void .ctor(Microsoft.Extensions.Options.IOptions`1[Microsoft.Extensions.Caching.Memory.MemoryCacheOptions])' on type 'MemoryCache'.
---> System.TypeLoadException: Method 'get_Size' in type 'Microsoft.Extensions.Caching.Memory.CacheEntry' from assembly 'Microsoft.Extensions.Caching.Memory, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' does not have an implementation.
at Microsoft.Extensions.Caching.Memory.MemoryCache..ctor(IOptions`1 optionsAccessor)
at lambda_method(Closure , Object[] )
at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
--- End of inner exception stack trace ---
at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
at Autofac.Core.Resolving.InstanceLookup.CreateInstance(IEnumerable`1 parameters)
--- End of inner exception stack trace ---
at Autofac.Core.Resolving.InstanceLookup.CreateInstance(IEnumerable`1 parameters)
at Autofac.Core.Resolving.InstanceLookup.Execute()
at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request)
at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(ResolveRequest request)
at Autofac.Core.Resolving.ResolveOperation.Execute(ResolveRequest request)
at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(ResolveRequest request)
at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType)
at Autofac.Extensions.DependencyInjection.AutofacServiceProvider.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at MyNamespace.Program.Main(String[] args)
I tried register all needed for caching services manually using autofac in ConfigureContainer instead of using .AddMemoryCache() as following (copy paste from .AddMemoryCache() body):
builder.RegisterType(typeof(OptionsManager<>)).As(typeof(IOptions<>)).SingleInstance();
builder.RegisterType(typeof(OptionsManager<>)).As(typeof(IOptionsSnapshot<>));
builder.RegisterType(typeof(OptionsMonitor<>)).As(typeof(IOptionsMonitor<>)).SingleInstance();
builder.RegisterType(typeof(OptionsMonitor<>)).As(typeof(IOptionsFactory<>)).SingleInstance();
builder.RegisterType(typeof(OptionsFactory<>)).As(typeof(IOptionsMonitorCache<>)).SingleInstance();
builder.RegisterType<MemoryCache>().As<IMemoryCache>().SingleInstance();
but in this case I get another exception:
System.ArgumentException: The type 'Microsoft.Extensions.Options.OptionsManager`1[TOptions]' is not assignable to service 'Microsoft.Extensions.Options.IOptions`1'.
at Autofac.Builder.RegistrationBuilder.CreateRegistration(Guid id, RegistrationData data, IInstanceActivator activator, Service[] services, IComponentRegistration target, Boolean isAdapterForIndividualComponent)
at Autofac.Builder.RegistrationBuilder.CreateRegistration[TLimit,TActivatorData,TSingleRegistrationStyle](IRegistrationBuilder`3 builder)
at Autofac.Builder.RegistrationBuilder.RegisterSingleComponent[TLimit,TActivatorData,TSingleRegistrationStyle](IComponentRegistryBuilder cr, IRegistrationBuilder`3 builder)
at Autofac.RegistrationExtensions.<>c__DisplayClass3_0.<RegisterType>b__0(IComponentRegistryBuilder cr)
at Autofac.ContainerBuilder.Build(IComponentRegistryBuilder componentRegistry, Boolean excludeDefaultModules)
at Autofac.ContainerBuilder.Build(ContainerBuildOptions options)
at Autofac.Extensions.DependencyInjection.AutofacServiceProviderFactory.CreateServiceProvider(ContainerBuilder containerBuilder)
at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
at Microsoft.Extensions.Hosting.HostBuilder.Build()
Any suggestions?
I found my mistake. Thanks to Sergey, I check my Program.cs and discovered that I use .AddMemoryCache() extension at one time with register IMemoryCache in ConfigureContainer. Only the extension method needs to be used, no manual registration of IMemoryCache needed.
Cannot use KeyFilter attribute to resolve registered type in asp.net core web api 2.2
I wanna use Autofac to resolve different instance of a type. I registered type in Startup.ConfigureServices by using RegisterType().Keyed and RegisterType().Named.
I can use IContainer.ResolveKeyed to resolve instance, but can't use KeyFilter to resolve instance in constructor
Startup
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public static IContainer Container { get; private set; }
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddControllersAsServices();
var builder = new ContainerBuilder();
builder.Populate(services);
builder.RegisterType<Foobar>().UsingConstructor(typeof(string)).WithParameter("name", "Eric").Named<Foobar>("Eric").SingleInstance();
builder.RegisterType<Foobar>().UsingConstructor(typeof(string)).WithParameter("name", "Fred").Keyed<Foobar>("Fred").SingleInstance();
Container = builder.Build();
var serviceProvider = new AutofacServiceProvider(Container);
return serviceProvider;
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseMvc();
}
}
ValuesController
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly Foobar fb1;
private readonly Foobar fb2;
public ValuesController([KeyFilter("Eric")]Foobar fbEric, [KeyFilter("Fred")]Foobar fbFred)
{
// KeyFilter not work
fb1 = fbEric;
fb2 = fbFred;
// Container.ResolvedKeyed work
fb1 = Startup.Container.ResolveKeyed<Foobar>("Eric");
fb2 = Startup.Container.ResolveNamed<Foobar>("Fred");
}
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { fb1.Say(), fb2.Say() };
}
}
Use KeyFilter will throw below exceptions:
An unhandled exception has occurred while executing the request.
Autofac.Core.DependencyResolutionException: An exception was thrown while activating Autofac.MI.WebApi.Controllers.ValuesController. ---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Autofac.MI.WebApi.Controllers.ValuesController' can be invoked with the available services and parameters:
Cannot resolve parameter 'Autofac.MI.ClassLib.Foobar fbEric' of constructor 'Void .ctor(Autofac.MI.ClassLib.Foobar, Autofac.MI.ClassLib.Foobar)'.
at Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(IComponentContext context, IEnumerable`1 parameters) in C:\projects\autofac\src\Autofac\Core\Activators\Reflection\ReflectionActivator.cs:line 160
at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) in C:\projects\autofac\src\Autofac\Core\Activators\Reflection\ReflectionActivator.cs:line 120
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget) in C:\projects\autofac\src\Autofac\Core\Resolving\InstanceLookup.cs:line 117
--- End of inner exception stack trace ---
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters, Object& decoratorTarget) in C:\projects\autofac\src\Autofac\Core\Resolving\InstanceLookup.cs:line 135
at Autofac.Core.Resolving.InstanceLookup.Execute() in C:\projects\autofac\src\Autofac\Core\Resolving\InstanceLookup.cs:line 83
at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) in C:\projects\autofac\src\Autofac\Core\Resolving\ResolveOperation.cs:line 131
at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) in C:\projects\autofac\src\Autofac\Core\Resolving\ResolveOperation.cs:line 84
at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance) in C:\projects\autofac\src\Autofac\ResolutionExtensions.cs:line 1041
at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters) in C:\projects\autofac\src\Autofac\ResolutionExtensions.cs:line 871
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.AspNetCore.Mvc.Controllers.ServiceBasedControllerActivator.Create(ControllerContext actionContext)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
For KeyFilter, you need to register the service with WithAttributeFiltering.
For AddControllersAsServices, it only register the service to service collection, but it did not register with WithAttributeFiltering.
Try code below:
services.AddMvc().AddControllersAsServices().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
var builder = new ContainerBuilder();
builder.Populate(services);
builder.RegisterType<Foobar>().UsingConstructor(typeof(string)).WithParameter("name", "Eric").Named<Foobar>("Eric").SingleInstance();
builder.RegisterType<Foobar>().UsingConstructor(typeof(string)).WithParameter("name", "Fred").Keyed<Foobar>("Fred").SingleInstance();
var controllers = typeof(Startup).Assembly.GetTypes().Where(t => t.BaseType == typeof(ControllerBase)).ToArray(); // for api controller
//var controllers = typeof(Startup).Assembly.GetTypes().Where(t => t.BaseType == typeof(Controller)).ToArray(); // for mvc controller
builder.RegisterTypes(controllers).WithAttributeFiltering();
Container = builder.Build();
I am trying to inject using Autofac:
Unhealthy event: SourceId='System.RA', Property='ReplicaOpenStatus', HealthState='Warning', ConsiderWarningAsError=false.
Replica had multiple failures during open on _Node_0. API call: IStatelessServiceInstance.Open(); Error = Autofac.Core.DependencyResolutionException (-2146233088)
An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = ServiceFabricProxy (DelegateActivator), Services = [MYSERVICE.ServiceFabric.ServiceFabric], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = ExternallyOwned ---> An error occurred during the activation of a particular registration. See the inner exception for
at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
at Autofac.Core.Resolving.InstanceLookup.Execute()
at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable`1 parameters)
at Autofac.Integration.ServiceFabric.StatelessServiceFactoryRegistration.<>c__DisplayClass0_0`1.b__0(StatelessServiceContext context)
at Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceFactory.System.Fabric.IStatelessServiceFactory.CreateInstance(String serviceTypeName, Uri serviceName, Byte[] initializationData, Guid partitionId, Int64 instanceId)
at System.Fabric.ServiceFactoryBroker.<>c__DisplayClass9_0.b__0(IStatelessServiceFactory factory, ServiceInitializationParameters initParams)
at System.Fabric.ServiceFactoryBroker.CreateHelper[TFactory,TReturnValue](IntPtr nativeServiceType, IntPtr nativeServiceName, UInt32 initializationDataLength, IntPtr nativeInitializationData, Guid partitionId, Func`3 creationFunc, Action`2 initializationFunc, ServiceInitializationParameters initializationParameters)
For more information see: http://aka.ms/sfhealth
These errors are always frustrating as they don't stop Visual Studio!
public ServiceFabric(StatelessServiceContext context, ServiceLoggerFactory serviceLoggerFactory, ServiceConfiguration configuration)
: base(context)
{
Argument.IsNotNull(() => context);
Argument.IsNotNull(() => serviceLoggerFactory);
Argument.IsNotNull(() => configuration);
_log = serviceLoggerFactory.EnrichLoggerForStatelessServiceContext(this);
_log.Information($"Service constructed {GetType().FullName}");
}
I have verified that the classes in my constructor have been registered:
public class NodeAutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
var assembly = typeof(GlobalAutofacModule).Assembly;
var appName = assembly.GetName().Name;
var appVersion = assembly.InformationalVersion();
builder.Register<ILogger>(container => LoggingHelper.ConfigureLogging(appName, appVersion))
.SingleInstance();
builder.RegisterType<ServiceLoggerFactory>()
.SingleInstance();
builder.RegisterType<ServiceConfiguration>()
.AsSelf()
.SingleInstance();
// TODO: Register services here
}
}
I find AutoFac really frustrating to work with when it can't resolve a constructor.
Are there any ways to get more information when this happens?
I am creating my container when my Service Fabric service starts up.
Paul
Cut stacktrace in SF errors is really annoying. But there is a way to get more details of the error. Try the following after configuration of your container:
using (var c = builder.Build())
{
var s = c.Resolve<ServiceFabric>();
}
Thus you'll get access to the full Exception information and will be able to specify the problem.
I have a class which requires a Func to be injected into its constructor. The class is called SomeClassThatNeedsFunc:
// register a factory function to create a db context to be used in singleton classes
services.AddTransient<Func<MyCustomContext>>(provider => (() =>
{
var dbContextOptionsBuilder = new DbContextOptionsBuilder<MyCustomContext>();
dbContextOptionsBuilder.UseSqlServer(sqlConnectionString);
return new MyCustomContext(dbContextOptionsBuilder.Options);
}));
// register class that needs the factory:
services.AddSingleton<SomeClassThatNeedsFunc>();
I get exception:
warn: Hangfire.AutomaticRetryAttribute[0]
Failed to process the job '4': an exception occurred. Retry attempt 3 of 10 will be performed in 00:01:55.
System.InvalidOperationException: Unable to resolve service for type 'System.Func`1[System.Threading.Tasks.VoidTaskResult]' while attempting to activate 'System.Threading.Tasks.Task`1[System.Threading.Tasks.VoidTaskResult]'.
at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type)
at Hangfire.AspNetCore.AspNetCoreJobActivatorScope.Resolve(Type type)
at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_0.<PerformJobWithFilters>b__0()
at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_1.<PerformJobWithFilters>b__2()
at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable`1 filters)
at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)
I have been working on a project, using OnionWebApiStarterKit as a foundation for learning my way around CQRS.
While the WebApi StudentsController example in the above OnionWebApiStarterKit project only injects IMediator, I decided it would be easier to also inject my custom IApplicationUserManager in the AccountController constructor, given its heavy reliance on user operations:
public AccountsController(
IMediator mediator,
IApplicationUserManager userManager)
{
// and so on...
}
But, this produces the following error:
"The requested service 'OnionWebApiStarterKit.Data.ISchoolDbContext'
has not been registered."
Full stack trace is below:
"message": "An error has occurred.",
"exceptionMessage": "An error occurred when trying to create a controller of type 'AccountsController'. Make sure that the controller has a parameterless public constructor.",
"exceptionType": "System.InvalidOperationException",
"stackTrace": " at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n at System.Web.Http.Tracing.Tracers.HttpControllerActivatorTracer.<>c__DisplayClass2.<System.Web.Http.Dispatcher.IHttpControllerActivator.Create>b__0()\r\n at System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEnd(ITraceWriter traceWriter, HttpRequestMessage request, String category, TraceLevel level, String operatorName, String operationName, Action`1 beginTrace, Action execute, Action`1 endTrace, Action`1 errorTrace)\r\n at System.Web.Http.Tracing.Tracers.HttpControllerActivatorTracer.System.Web.Http.Dispatcher.IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n at System.Web.Http.Tracing.Tracers.HttpControllerDescriptorTracer.<>c__DisplayClass2.<CreateController>b__0()\r\n at System.Web.Http.Tracing.ITraceWriterExtensions.TraceBeginEnd(ITraceWriter traceWriter, HttpRequestMessage request, String category, TraceLevel level, String operatorName, String operationName, Action`1 beginTrace, Action execute, Action`1 endTrace, Action`1 errorTrace)\r\n at System.Web.Http.Tracing.Tracers.HttpControllerDescriptorTracer.CreateController(HttpRequestMessage request)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()",
"innerException": {
"message": "An error has occurred.",
"exceptionMessage": "The requested service 'OnionWebApiStarterKit.Data.ISchoolDbContext' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.",
"exceptionType": "Autofac.Core.Registration.ComponentNotRegisteredException",
"stackTrace": " at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context)\r\n at OnionWebApiStarterKit.Bootstrapper.IdentityModule.<>c.<Load>b__2_0(IComponentContext b) in C:\\Projects\\OnionWebApiStarterKit\\OnionWebApiStarterKit.Bootstrapper\\App_Start\\IdentityModule.cs:line 33\r\n at Autofac.RegistrationExtensions.<>c__DisplayClass10`1.<Register>b__f(IComponentContext c, IEnumerable`1 p)\r\n at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass1`1.<ForDelegate>b__0(IComponentContext c, IEnumerable`1 p)\r\n at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.<Execute>b__0()\r\n at Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid id, Func`1 creator)\r\n at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Registration.ExternalRegistrySource.<>c__DisplayClass8.<RegistrationsFor>b__3(IComponentContext c, IEnumerable`1 p)\r\n at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)\r\n at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context)\r\n at OnionWebApiStarterKit.Bootstrapper.IdentityModule.<>c.<Load>b__2_1(IComponentContext b) in C:\\Projects\\OnionWebApiStarterKit\\OnionWebApiStarterKit.Bootstrapper\\App_Start\\IdentityModule.cs:line 37\r\n at Autofac.RegistrationExtensions.<>c__DisplayClass10`1.<Register>b__f(IComponentContext c, IEnumerable`1 p)\r\n at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass1`1.<ForDelegate>b__0(IComponentContext c, IEnumerable`1 p)\r\n at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.<Execute>b__0()\r\n at Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid id, Func`1 creator)\r\n at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Registration.ExternalRegistrySource.<>c__DisplayClass8.<RegistrationsFor>b__3(IComponentContext c, IEnumerable`1 p)\r\n at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass2.<CanSupplyValue>b__0()\r\n at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()\r\n at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.<Execute>b__0()\r\n at Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid id, Func`1 creator)\r\n at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Registration.ExternalRegistrySource.<>c__DisplayClass8.<RegistrationsFor>b__3(IComponentContext c, IEnumerable`1 p)\r\n at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass2.<CanSupplyValue>b__0()\r\n at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()\r\n at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Registration.ExternalRegistrySource.<>c__DisplayClass8.<RegistrationsFor>b__3(IComponentContext c, IEnumerable`1 p)\r\n at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)\r\n at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType, IEnumerable`1 parameters)\r\n at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType)\r\n at Autofac.Integration.WebApi.AutofacWebApiDependencyScope.GetService(Type serviceType)\r\n at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"
}
I am registering my dependencies from my bootstrapped Startup class:
IocConfig.RegisterDependencies(app);
And I confirmed it does get hit by setting a break-point. Below are my registrations:
public static void RegisterDependencies(IAppBuilder app)
{
DbContextScopeExtensionConfig.Setup();
// Get your HttpConfiguration. In OWIN, you'll create one
// rather than using GlobalConfiguration.
var config = new HttpConfiguration();
// register Auto Mapper
AutoMapperConfig.Initialize();
// register api routing.
WebApiConfig.Register(config);
// Run optional steps, like registering filters,
// per-controller-type services, etc.
var builder = new ContainerBuilder();
// Register Web API controller in executing assembly.
builder.RegisterApiControllers(Assembly.Load("OnionWebApiStarterKit.WebApi"));
//Helper nuget for managing the DbContext lifetime in Entity Framework. Please see: http://mehdi.me/ambient-dbcontext-in-ef6/
builder.RegisterType<DbContextScopeFactory>().As<IDbContextScopeFactory>().SingleInstance();
builder.RegisterType<AmbientDbContextLocator>().As<IAmbientDbContextLocator>().SingleInstance();
// Registers our IMediator (abstraction for observer pattern, which lets us use CQRS)
builder.RegisterModule(new MediatorModule(Assembly.Load("OnionWebApiStarterKit.Services")));
// Registers our Fluent Validations that we use on our Models
builder.RegisterModule(new FluentValidationModule(Assembly.Load("OnionWebApiStarterKit.WebApi"), Assembly.Load("OnionWebApiStarterKit.Services")));
// Registers our AutoMapper Profiles
builder.RegisterModule(new AutoMapperModule(Assembly.Load("OnionWebApiStarterKit.WebApi"), Assembly.Load("OnionWebApiStarterKit.Services")));
// Registers our ASP.NET Identity custom classes.
builder.RegisterModule(new IdentityModule(Assembly.Load("OnionWebApiStarterKit.Data"), Assembly.Load("OnionWebApiStarterKit.Core")));
// Set the dependency resolver to be Autofac.
var container = builder.Build();
// helps view registered autofac dependencies.
// container.IsRegistered();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// Register the Autofac middleware FIRST, then the Autofac Web API middleware,
// and finally the standard Web API middleware.
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseCors(CorsOptions.AllowAll); // Enables crossdomain requests
app.UseWebApi(config);
}
In the above file, the below module handles Identity registrations, which IApplicationUserManager is part of:
// Registers our ASP.NET Identity custom classes.
builder.RegisterModule(new IdentityModule(Assembly.Load("OnionWebApiStarterKit.Data"), Assembly.Load("OnionWebApiStarterKit.Core")));
And here is how my Identity stuff is registered:
public IdentityModule(params System.Reflection.Assembly[] assembliesToScan)
: base()
{
_assembliesToScan = assembliesToScan;
}
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType(typeof(ApplicationUserManager)).As(typeof(IApplicationUserManager)).InstancePerRequest();
builder.RegisterType(typeof(ApplicationRoleManager)).As(typeof(IApplicationRoleManager)).InstancePerRequest();
builder.RegisterType(typeof(ApplicationIdentityUser)).As(typeof(IUser<int>)).InstancePerRequest();
builder.Register(b => b.Resolve<ISchoolDbContext>() as DbContext).InstancePerRequest();
builder.Register(b =>
{
var manager = IdentityFactory.CreateUserManager(b.Resolve<DbContext>());
if (Startup.DataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationIdentityUser, int>(
Startup.DataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}).InstancePerRequest();
builder.Register(b => IdentityFactory.CreateRoleManager(b.Resolve<DbContext>())).InstancePerRequest();
builder.Register(b => HttpContext.Current.Request.GetOwinContext().Authentication).InstancePerRequest();
}
As you can see, ISchoolDbContext is clearly registered at this line:
builder.Register(b => b.Resolve<ISchoolDbContext>() as DbContext).InstancePerRequest();
This is the same line that Autofac complains about in the stack trace:
at
OnionWebApiStarterKit.Bootstrapper.IdentityModule.<>c.b__2_0(IComponentContext
b) in
C:\Projects\OnionWebApiStarterKit\OnionWebApiStarterKit.Bootstrapper\App_Start\IdentityModule.cs:line
33
I am a bit stumped as to why injecting IApplicationUserManager is telling me I have not registered my ISchoolDbContext?
Thanks.
UPDATE
It looks like I wasn't scanning my passed-in assemblies in the IdentityModule.
So, I have updated my code accordingly:
// Register our UserManager
builder.RegisterAssemblyTypes(_assembliesToScan)
.As<IApplicationUserManager>().InstancePerRequest();
//// Register our RoleManager
builder.RegisterAssemblyTypes(_assembliesToScan)
.As<IApplicationRoleManager>().InstancePerRequest();
builder.RegisterAssemblyTypes(_assembliesToScan)
.As<IUser<int>>().InstancePerRequest();
I assume you have a persistence layer or a similar class library for your database operations.
Have you registered all the types in that assembly? Something like below:
var assembly = typeof(DbContextScopeFactory).Assembly;
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.Name.StartsWith("SomeInterface"))
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.Name.EndsWith("DbContext"))
.AsImplementedInterfaces();