好的,我收到了熟悉的错误:
尝试创建类型的控制器时发生错误 '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显然在启动时无法识别。
知道我做错了什么吗?