Autofac - 请求的服务(lSomeDbContext)尚未注册

时间:2016-11-17 05:54:01

标签: c# entity-framework autofac

我一直致力于一个项目,使用OnionWebApiStarterKit作为学习CQRS的基础。

虽然上面的OnionWebApiStarterKit项目中的WebApi StudentsController示例只注入IMediator,但我认为在AccountController构造函数中注入我的自定义IApplicationUserManager会更容易,因为它严重依赖用户操作:

public AccountsController(
    IMediator mediator, 
    IApplicationUserManager userManager)
{
    // and so on...

}

但是,这会产生以下错误:

  

“请求的服务'OnionWebApiStarterKit.Data.ISchoolDbContext'   尚未注册。“

完整堆栈跟踪如下:

"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)"
  }

我正从我的bootstrapped Startup类中注册我的依赖项:

IocConfig.RegisterDependencies(app);

我确认它确实受到设定断点的打击。以下是我的注册:

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);

        }

在上面的文件中,下面的模块处理身份注册,IApplicationUserManager是其中的一部分:

// Registers our ASP.NET Identity custom classes.
            builder.RegisterModule(new IdentityModule(Assembly.Load("OnionWebApiStarterKit.Data"), Assembly.Load("OnionWebApiStarterKit.Core")));

以下是我的身份资料的注册方式:

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();

        }

正如您所看到的,ISchoolDbContext显然已在此行注册:

 builder.Register(b => b.Resolve<ISchoolDbContext>() as DbContext).InstancePerRequest();

这与Autofac在堆栈跟踪中抱怨的行相同:

  

在   OnionWebApiStarterKit.Bootstrapper.IdentityModule&LT;&GT; c.b__2_0(IComponentContext   b)in   C:\项目\ OnionWebApiStarterKit \ OnionWebApiStarterKit.Bootstrapper \ App_Start \ IdentityModule.cs:行   33

我有点难过为什么注入IApplicationUserManager告诉我我没有注册我的ISchoolDbContext?

感谢。

更新

看起来我没有在IdentityModule中扫描传入的程序集。 所以,我相应地更新了我的代码:

// 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();

1 个答案:

答案 0 :(得分:0)

我假设您有数据库操作的持久层或类似的类库。 你在那个装配中注册了所有类型吗?如下所示:

           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();