错误:确保控制器具有无参数的公共构造函数(Autofac,WebApi2和Onion Architecture)

时间:2016-10-12 18:26:07

标签: c# asp.net-web-api autofac onion-architecture

好的,我收到了熟悉的错误:

  

尝试创建类型的控制器时发生错误   'UserController的'。确保控制器具有无参数   公共建设者。 ---> System.ArgumentException:Type   'Project.WebApi.Controllers.UserController'没有默认值   System.Linq.Expressions.Expression.New(Type type)

中的构造函数

我正在构建一个使用Onion Architecture的WebApi2项目(没有MVC前端),将我的大部分启动代码放在Bootstrap项目的App_Start中。以下是相关课程:

WebAPI项目代码:

UserController.cs

//[Authorize]
    [RoutePrefix("api/v1")]
    public class UserController : ApiController
    {
        private readonly IMediator _mediator;

        public UserController(IMediator mediator)
        {
            if (mediator == null)
                throw new ArgumentNullException(nameof(mediator), "mediator");
            _mediator = mediator;
        }

        // GET api/v1/users
        [HttpGet]
        [Route("users")]
        public async Task<IEnumerable<User>> Get()
        {

            var users = await _mediator.SendAsync(new AsyncGenericQuery<User>(20));

            return users;

        }

        // Other methods taken out for brevity.

Global.asax中

public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AutoMapperConfig.Initialize();
            GlobalConfiguration.Configure(WebApiConfig.Register);

        }
    }

App_Start / WebApiConfig:

public static void Register(HttpConfiguration config)
        {
            // Enable debugging, remove in upper env.
            config.EnableSystemDiagnosticsTracing();

            // Web API configuration and services
            var validatorFactory = new FluentValidatorFactory();
            FluentValidationModelValidatorProvider.Configure(config, provider => provider.ValidatorFactory = validatorFactory);

            // Action Filters
            config.Filters.Add(new FluentValidationActionFilter());

            // Exception Filter
            config.Filters.Add(new ServiceExceptionFilterAttribute());

            config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Never;

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }


   );
    }
}

引导程序项目代码

App_Start / Startup.cs

public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);

        }
    }

App_Start / Statup.Auth.cs

public partial class Startup
    {
        public static IDataProtectionProvider DataProtectionProvider { get; private set; }

        public void ConfigureAuth(IAppBuilder app)
        {
            DataProtectionProvider = app.GetDataProtectionProvider();

            //Removed auth logic...

        }
    }

App_Start / IocConfig.cs

public class IocConfig
    {
        public static void RegisterDependencies()
        {
            DbContextScopeExtensionConfig.Setup();

            var builder = new ContainerBuilder();

            // Get HttpConfiguration
            var config = GlobalConfiguration.Configuration;

            //builder.RegisterApiControllers(typeof(WebApiApplication).Assembly);

            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

            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("Project.Services")));

            // Registers our Fluent Validations that we use on our Models
            builder.RegisterModule(new FluentValidationModule(Assembly.Load("Project.WebApi"), Assembly.Load("Project.Services")));

            // Registers our AutoMapper Profiles
            builder.RegisterModule(new AutoMapperModule(Assembly.Load("Project.WebApi"), Assembly.Load("Project.Services")));

            // Registers our Identity
            builder.RegisterModule(new IdentityModule(Assembly.Load("Project.WebApi"), Assembly.Load("Project.Services")));

            var container = builder.Build();

            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);


        }

App_Start / MediatorModule.cs

public class MediatorModule : Module
    {
        private readonly System.Reflection.Assembly[] _assembliesToScan;

        public MediatorModule(params System.Reflection.Assembly[] assembliesToScan)
            : base()
        {
            _assembliesToScan = assembliesToScan;
        }

        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterSource(new ContravariantRegistrationSource());
            builder.RegisterAssemblyTypes(typeof(IMediator).Assembly).AsImplementedInterfaces();

            // Register our Procedures
            builder.RegisterAssemblyTypes(_assembliesToScan)
                .Where(t => t.GetInterfaces().Any(i => i == typeof(IProcedure)))
                .AsSelf()
                .InstancePerDependency();

            // Register our PreRequestHandler
            builder.RegisterAssemblyTypes(_assembliesToScan)
                .AsClosedTypesOf(typeof(IPreRequestHandler<>))
                .SingleInstance();

            builder.RegisterAssemblyTypes(_assembliesToScan)
                .AsClosedTypesOf(typeof(IAsyncPreRequestHandler<>))
                .SingleInstance();


            builder.ScanRegisterAndDecorate(
                _assembliesToScan,
                typeof(IDatabaseService),
                typeof(IAsyncRequestHandler<,>),
                typeof(AsyncMediatorPipeline<,>),
                typeof(AsyncDbContextScopeBoundary<,>),
                typeof(AsyncValidatorHandler<,>),
                typeof(ExceptionLoggerAsync<,>),
                typeof(AsyncLoggingHandler<,>)
            );

            builder.ScanRegisterAndDecorate(
                _assembliesToScan,
                typeof(IDatabaseService),
                typeof(IRequestHandler<,>),
                typeof(MediatorPipeline<,>),
                typeof(DbContextScopeBoundary<,>),
                typeof(ValidatorHandler<,>),
                typeof(ExceptionLogger<,>),
                typeof(LoggingHandler<,>)
            );

            #region Generic Helper Query Services

            // Special registration of our Automapper Handler
            builder.RegisterGeneric(typeof(AutoMapperQuery<,>)).AsSelf();
            builder.RegisterGeneric(typeof(AutoMapperQueryHandler))
                .As(typeof(IRequestHandler<,>))
                .SingleInstance();

            builder.RegisterGeneric(typeof(AsyncAutoMapperQuery<,>)).AsSelf();
            builder.RegisterGeneric(typeof(AsyncAutoMapperQueryHandler<,>))
                .As(typeof(IAsyncRequestHandler<,>))
                .SingleInstance();

            // Special Registration of our Generic Query Handler
            builder.RegisterGeneric(typeof(GenericQuery<>)).AsSelf();
            builder.RegisterGeneric(typeof(GenericQueryHandler))
                .As(typeof(IRequestHandler<,>))
                .SingleInstance();

            builder.RegisterGeneric(typeof(AsyncGenericQuery<>)).AsSelf();
            builder.RegisterGeneric(typeof(AsyncGenericQueryHandler<>))
                .As(typeof(IAsyncRequestHandler<,>))
                .SingleInstance();

            // Special Registration of our Pagination Query Handler
            builder.RegisterGeneric(typeof(PaginateQuery<>)).AsSelf();
            builder.RegisterGeneric(typeof(PaginateQueryHandler))
                .As(typeof(IRequestHandler<,>))
                .SingleInstance();

            builder.RegisterGeneric(typeof(AsyncPaginateQuery<>)).AsSelf();
            builder.RegisterGeneric(typeof(AsyncPaginateQueryHandler))
                .As(typeof(IAsyncRequestHandler<,>))
                .SingleInstance();

            #endregion

            // Sets the delegate resolver factories for Mediatr.
            // These factories are used by Mediatr to find the appropriate Handlers
            builder.Register<SingleInstanceFactory>(ctx =>
            {
                var c = ctx.Resolve<IComponentContext>();
                return t => c.Resolve(t);
            });
            builder.Register<MultiInstanceFactory>(ctx =>
            {
                var c = ctx.Resolve<IComponentContext>();
                return t => (IEnumerable<object>) c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
            });
        }
    }

在IocConfig文件中的Bootstrapper命名空间中,我有:

  

[assembly:WebActivatorEx.PreApplicationStartMethod(typeof(IocConfig),   “RegisterDependencies”)]

这应该将我的类型注册为应用程序启动过程的一部分。在这个文件中,我正在注册我的控制器:

builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

但是,我的UserController显然在启动时无法识别。

知道我做错了什么吗?

0 个答案:

没有答案