我正在使用webapi,unity和mvc。我收到错误“确保控制器具有无参数的公共构造函数”。我已经看到类似的问题,但仍然无法让它工作。我已经安装了unity.webapi,似乎有所有必要的参考资料:
我验证了所有内容与本网站上的内容相符:
这就是我所拥有的:
引导程序:
public static class Bootstrapper
{
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<IDatabaseFactoryHouseDB, DatabaseFactoryHouseDB>(new HierarchicalLifetimeManager());
container.RegisterType<UnitOfWorkHouseDB>();
// repositories
container.RegisterType<IEmployeeRepository, EmployeeRepository>();
// services
container.RegisterType<IEmployeeService, EmployeeService>();
RegisterTypes(container);
return container;
}
public static void RegisterTypes(IUnityContainer container) { }
}
的Global.asax:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Database.SetInitializer<HouseDBContext>(null);
Bootstrapper.Initialise();
//required for setting routes in the attributes of a controller method
GlobalConfiguration.Configuration.EnsureInitialized();
}
}
Api控制器:
public class EmployeeApiController : ApiController
{
private readonly IEmployeeService employeeService;
public EmployeeApiController(IEmployeeService employeeService)
{
this.employeeService = employeeService;
}
// rest of controller
}
WebApiConfig:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// use json strings as the default return value for the app
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
// Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
// To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
// For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
//config.EnableQuerySupport();
// To disable tracing in your application, please comment out or remove the following line of code
// For more information, refer to: http://www.asp.net/web-api
config.EnableSystemDiagnosticsTracing();
}
UnityConfig:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
不确定我错过了什么。
编辑:我注意到我的App_Start文件夹中有一个UnityConfig类。在查看Sarathy的评论后,我意识到它没有被调用。我在global.asax中注释掉了我的bootstrapper初始化,并添加了UnityConfig.RegisterComponents()行,所以现在我的global.asax看起来像这样:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
UnityConfig.RegisterComponents(); // <--- added
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Database.SetInitializer<HouseDBContext>(null);
//Bootstrapper.Initialise(); <-- not using bootstrapper anymore
//required for setting routes in the attributes of a controller method
GlobalConfiguration.Configuration.EnsureInitialized();
}
}
我的UnityConfig看起来像这样:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IDatabaseFactoryHouseDB, DatabaseFactoryHouseDB>(new HierarchicalLifetimeManager());
//container.RegisterType<IUnitOfWork>();
container.RegisterType<UnitOfWorkHouseDB>();
// repositories
container.RegisterType<IEmployeeRepository, EmployeeRepository>();
// services
container.RegisterType<IEmployeeService, EmployeeService>();
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}
然而,我仍然得到无参数构造函数错误。有趣的是,即使我添加了无参数构造函数:
public class EmployeeApiController : ApiController
{
private readonly IEmployeeService employeeService;
public EmployeeApiController()
: base()
{
}
public EmployeeApiController(IEmployeeService employeeService)
{
this.employeeService = employeeService;
}
}
使用unityconfig方法时仍然出现错误。使用bootstrapper,我没有收到错误,但我的服务没有初始化。
我完全糊涂了。不知怎的,我觉得我混合了MVC和WebApi,事情没有正确解决......
编辑2:
我查看了无参数构造函数错误的内部异常,并注意到它提到了我的IUnitOfWork类:
“依赖关系的解析失败,type = \“AngularMVC.Controllers.EmployeeApiController \”,name = \“(无)\”。\ r \ n发生以下情况时发生异常:解析时。\ r \ n \ nException is:InvalidOperationException - 当前类型, AngularMVC.Models.Interfaces.IUnitOfWork,是一个接口而不能 被建造。你错过了一个类型吗? 映射吗?\ r \ n ---------------------------------------- ------- \ r \ nAtt 异常时间,容器是:\ r \ n \ r \ n解析 AngularMVC.Controllers.EmployeeApiController,(无)\ r \ n解析 参数\“employeeService \”的构造函数 AngularMVC.Controllers.EmployeeApiController(AngularMVC.Services.IEmployeeService employeeService)\ r \ n解析 AngularMVC.Services.EmployeeService,(无)(映射自 AngularMVC.Services.IEmployeeService,(无))\ r \ n解析 参数\“unitOfWork \”的构造函数 AngularMVC.Services.EmployeeService(AngularMVC.Models.Repositories.IEmployeeRepository employeeRepository,AngularMVC.Models.Interfaces.IUnitOfWork unitOfWork)\ r \ n解析 AngularMVC.Models.Interfaces.IUnitOfWork,(无)\ r \ n“个
只有这个:
public interface IUnitOfWork
{
void Commit();
}
当我在UnityConfig中执行以下操作时:
container.RegisterType<IUnitOfWork>();
IUnitOfWork sm = container.Resolve<IUnitOfWork>();
我得到同样的错误,声明“当前类型,AngularMVC.Models.Interfaces.IUnitOfWork,是一个接口,无法构造。你错过了类型映射吗?”
答案 0 :(得分:3)
从您的代码中,我可以看到您使用Unity作为您的IoC容器。 IoC Container将处理控制器类的初始化。
要使IoC容器创建控制器的实例,您的控制器类需要具有无参数的公共构造函数(也称为默认构造函数)。
public class EmployeeApiController : ApiController
{
private readonly IEmployeeService employeeService;
public EmployeeAPIController() : base()
{
}
public EmployeeApiController(IEmployeeService employeeService)
{
this.employeeService = employeeService;
}
}
更新时间:2015年2月18日 从您的代码我还没有看到IUnitOfWork接口的实现。工作单元是在域中心建模中广泛使用的模式。通常,工作单元模式与存储库模式一起使用。工作单元的目的是使多个存储库可以在同一个数据库上下文中工作。
从您的代码中注册
//container.RegisterType<IUnitOfWork>();
container.RegisterType<UnitOfWorkHouseDB>();
但是,我认为你应该注册这样的代码:(我假设UnitOfWorkHouseDB是IUnitOfWork的实现)
container.RegisterType<IUnitOfWork, UnitOfWorkHouseDB>();
其中类似于:( EmployeeRepository是IEmployeeRepository的实现)
// repositories
container.RegisterType<IEmployeeRepository, EmployeeRepository>();
通常,当我使用工作单元和存储库模式时,我将执行以下结构:
IUnitOfWork界面
public interface IUnitOfWork
{
void Commit();
}
IUnitOfWork实施:
public class UnitOfWork : IUnitOfWork
{
//DBContext could your own db context, or a interface, like IDatabaseFactoryHouseDB
private DBContext _ctx;
public UnitOfWork(DbContext ctx)
{
_ctx = ctx;
}
private IEmployeeRepository _EmployeeRepository;
public IEmployeeRepository EmployeeRepository
{
get { return _EmployeeRepository ?? (_EmployeeRepository = new EmployeeRepository(_ctx)); }
}
private ICustomerRepository _CustomerRepository;
public ICustomerRepository CustomerRepository
{
get { return _CustomerRepository ?? (_CustomerRepository = new CustomerRepository(_ctx)); }
}
public void Commit()
{
_ctx.SaveChange();
}
}