问题
OK, I am getting the familiar error:
An error occurred when trying to create a controller of type 'UserController'. Make sure that the controller has a parameterless public constructor. ---> System.ArgumentException: Type 'Project.WebApi.Controllers.UserController' does not have a default constructor at System.Linq.Expressions.Expression.New(Type type)
I am building a WebApi2 project (no MVC front end) that use Onion Architecture, putting most of my start-up code in App_Start of a Bootstrap project. Here are the relevant classes:
WebAPI Project Code:
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 }
);
}
}
Bootstrapper Project Code
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));
});
}
}
Over the Bootstrapper namespace in the IocConfig file, I have:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(IocConfig), "RegisterDependencies")]
This should register my types as part of the application startup process. In this file, I am registering my controllers:
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
However, my UserController is obviously not getting recognized at startup.
Any idea what I am doing wrong?
来源:https://stackoverflow.com/questions/40005815/error-make-sure-that-the-controller-has-a-parameterless-public-constructor-aut