错误:确保控制器有一个无参数的公共构造函数webapi [英] error: Make sure that the controller has a parameterless public constructor webapi

查看:320
本文介绍了错误:确保控制器有一个无参数的公共构造函数webapi的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用webapi,unity和mvc。我得到错误确保控制器有一个无参数的公共构造函数。我已经看到类似的问题,但仍然不能得到它的工作。我已经安装了unity.webapi,似乎有所有必要的参考:




  • Microsoft.Practices.Unity - runtime:v4.0.30319,version :3.5.0.0

  • Microsoft.Practices.Unity.Mvc - runtime:v4.0.30319,version:3.5.0.0

  • Unity.WebApi - runtime :v4.0.30319,version:5.1.0.0

  • System.Web.Http - runtime:v4.0.30319,version:5.2.2.0

  • 系统.Web.Mvc - runtime:v4.0.30319,version:5.2.2.0



我验证了一切与此网站上的内容相符: / p>

http://www.asp.net/mvc/overview/releases/how-to-upgrade -an-aspnet-mvc-4-and-web-api-project-to-aspnet-mvc-5-and-web-api-2



这里是我有:



Bootstrapper:

  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();
//在控制器方法的属性中设置路由所需的
GlobalConfiguration.Configuration.EnsureInitialized();
}
}

Api控制器:

  public class EmployeeApiController:ApiController 
{
private readonly IEmployeeService employeeService;

public EmployeeApiController(IEmployeeService employeeService)
{
this.employeeService = employeeService;
}

//控制器的其余部分
}

WebApiConfig:

  public static void注册(HttpConfiguration config)
{
config.MapHttpAttributeRoutes ;

config.Routes.MapHttpRoute(
name:DefaultApi,
routeTemplate:api / {controller} / {id},
默认值:new { id = RouteParameter.Optional}
);

//使用json字符串作为应用程序的默认返回值
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(text / html));

//取消注释以下代码行以启用对具有IQueryable或IQueryable< T>的动作的查询支持。返回类型。
//为了避免处理意外或恶意查询,请使用QueryableAttribute上的验证设置验证传入的查询。
//有关详细信息,请访问http://go.microsoft.com/fwlink/?LinkId=279712。
//config.EnableQuerySupport();

//要在应用程序中禁用跟踪,请注释掉或删除以下代码行
//有关详细信息,请参阅: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的评论后,我意识到这不是被调用。我注释掉了我的bootstrapper初始化在global.asax和添加行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(); < - 不再使用bootstrapper
//在控制器方法的属性中设置路由所需的
GlobalConfiguration.Configuration.EnsureInitialized();
}
}

并且我的UnityConfig看起来像这样:

  public static class UnityConfig 
{
public static void RegisterComponents()
{
var container = new UnityContainer();

//使用容器注册所有组件
//不需要注册您的控制器

//例如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: b

我查看了无参数构造函数错误的内部异常,并注意到它提到了我的IUnitOfWork类:


解决依赖失败,type =
\AngularMVC.Controllers.EmployeeApiController\,name =
\(无)\。\r\\\
Exception发生时:而解析。\r\\\
Exception
是:InvalidOperationException - 当前类型,
AngularMVC.Models.Interfaces.IUnitOfWork,是一个接口,不能
构造。缺少类型
映射
?\r\\\
------------------------------- ---------------- \r\\\

时间的异常,容器是:\r\\\
\r\\\
解决
AngularMVC.Controllers.EmployeeApiController,(none)\r\\\
解析
参数\employeeService\的构造函数
AngularMVC.Controllers.EmployeeApiController(AngularMVC.Services.IEmployeeService
employeeService)\r\\\
解析
AngularMVC.Services.EmployeeService,(none)(从
映射AngularMVC.Services.IEmployeeService,(none))\r\\\
解析
参数\unitOfWork \的构造函数
AngularMVC.Services.EmployeeService(AngularMVC.Models.Repositories.IEmployeeRepository
employeeRepository,AngularMVC.Models.Interfaces.IUnitOfWork
unitOfWork)\ r \\\
解析
AngularMVC.Models.Interfaces.IUnitOfWork,(无)\r\\\


只是这样:

  public interface IUnitOfWork 
{
void Commit
}

当我在UnityConfig中执行以下操作时:

  container.RegisterType< IUnitOfWork>(); 
IUnitOfWork sm = container.Resolve< IUnitOfWork>();

我得到相同的错误,说明当前类型AngularMVC.Models.Interfaces.IUnitOfWork

解决方案

在你的代码中,我可以看到你使用的是Unity作为您的IoC容器。 IoC Container将处理控制器类的初始化。



要使IoC容器创建控制器的实例,您的控制器类需要有一个无参数的公共构造函数(也称为默认构造函数)。

  public class EmployeeApiController:ApiController 
{
private readonly IEmployeeService employeeService;

public EmployeeAPIController():base()
{
}

public EmployeeApiController(IEmployeeService employeeService)
{
.employeeService = employeeService;
}
}

更新1: strong>
从你的代码我没有看到IUnitOfWork接口的实现。工作单元是广泛用于域中心建模的模式。通常,工作单元模式与存储库模式一起使用。



从您的代码中,您注册

  // container.RegisterType< IUnitOfWork>(); 
container.RegisterType< UnitOfWorkHouseDB>();然而,我认为你应该有这样的注册代码:(我假设UnitOfWorkHouseDB是IUnitOfWork的实现(我假设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可以是您自己的数据库上下文,或者是一个接口,如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();
}
}


I am using webapi, unity, and mvc. I am getting the error "Make sure that the controller has a parameterless public constructor". I have seen treads on similar problems but still can't get it to work. I have installed unity.webapi and seem to have all the necessary references:

  • Microsoft.Practices.Unity - runtime: v4.0.30319, version: 3.5.0.0
  • Microsoft.Practices.Unity.Mvc - runtime: v4.0.30319, version: 3.5.0.0
  • Unity.WebApi - runtime: v4.0.30319, version: 5.1.0.0
  • System.Web.Http - runtime: v4.0.30319, version: 5.2.2.0
  • System.Web.Mvc - runtime: v4.0.30319, version: 5.2.2.0

I verified everything matches what is on this site:

http://www.asp.net/mvc/overview/releases/how-to-upgrade-an-aspnet-mvc-4-and-web-api-project-to-aspnet-mvc-5-and-web-api-2

Here is what I have:

Bootstrapper:

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 controller:

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

Not sure what I am missing.

Edit: I noticed I had a UnityConfig class in my App_Start folder. After looking into the comment by Sarathy, I realized it wasn't be called. I commented out my bootstrapper initialization in the global.asax and added the line UnityConfig.RegisterComponents(), so now my global.asax looks like this:

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

and my UnityConfig looks like this:

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

Yet I still get the parameterless constructor error. What is funny is even though I have added a parameterless constructor:

    public class EmployeeApiController : ApiController
    {
        private readonly IEmployeeService employeeService;

        public EmployeeApiController()
            : base()
        {
        } 

        public EmployeeApiController(IEmployeeService employeeService)
        {
            this.employeeService = employeeService;
        }
}

I still get the error when using the unityconfig approach. With bootstrapper, I didn't get the error but my services were not initialized.

I am totally confused. Somehow I feel I am mixing MVC and WebApi and things are not resolving correctly...

EDIT 2:

I looked at the inner exception of my parameterless constructor error and noticed it is mentioning my IUnitOfWork class:

"Resolution of the dependency failed, type = \"AngularMVC.Controllers.EmployeeApiController\", name = \"(none)\".\r\nException occurred while: while resolving.\r\nException is: InvalidOperationException - The current type, AngularMVC.Models.Interfaces.IUnitOfWork, is an interface and cannot be constructed. Are you missing a type mapping?\r\n-----------------------------------------------\r\nAt the time of the exception, the container was:\r\n\r\n Resolving AngularMVC.Controllers.EmployeeApiController,(none)\r\n Resolving parameter \"employeeService\" of constructor AngularMVC.Controllers.EmployeeApiController(AngularMVC.Services.IEmployeeService employeeService)\r\n Resolving AngularMVC.Services.EmployeeService,(none) (mapped from AngularMVC.Services.IEmployeeService, (none))\r\n Resolving parameter \"unitOfWork\" of constructor AngularMVC.Services.EmployeeService(AngularMVC.Models.Repositories.IEmployeeRepository employeeRepository, AngularMVC.Models.Interfaces.IUnitOfWork unitOfWork)\r\n Resolving AngularMVC.Models.Interfaces.IUnitOfWork,(none)\r\n"

which is only this:

public interface IUnitOfWork
{
    void Commit();
}

When I do the following in my UnityConfig:

        container.RegisterType<IUnitOfWork>();
        IUnitOfWork sm = container.Resolve<IUnitOfWork>();

I get the same error stating "The current type, AngularMVC.Models.Interfaces.IUnitOfWork, is an interface and cannot be constructed. Are you missing a type mapping?"

解决方案

From your code, I can see you are using Unity as your IoC Container. IoC Container will handle the initialization of controller class.

To make IoC container to create a instance of your controller, your controller class needs to have a parameterless public constructor(aka default constructor).

public class EmployeeApiController : ApiController
{
    private readonly IEmployeeService employeeService;

    public EmployeeAPIController() : base()
    {
    }

    public EmployeeApiController(IEmployeeService employeeService)
    {
        this.employeeService = employeeService;
    }
}

UPDATE 1: 18 Feb 2015 From your code I have not seen a implementation of IUnitOfWork interface. The unit of work is pattern that is widely used in domain central modeling. Normally, unit of work pattern is used with repository pattern together. The purpose of of unit of work, is to make multiple repository can working on a same database context.

From your code, you register

//container.RegisterType<IUnitOfWork>();
container.RegisterType<UnitOfWorkHouseDB>();

However, I think you should have register code like this: (I assume UnitOfWorkHouseDB is the implementation of IUnitOfWork)

container.RegisterType<IUnitOfWork, UnitOfWorkHouseDB>();

Which is similar as: (EmployeeRepository is the implementation of IEmployeeRepository)

// repositories
container.RegisterType<IEmployeeRepository, EmployeeRepository>();

Normally, when I use unit of work and repository pattern, I will do following structure:

IUnitOfWork interface

public interface IUnitOfWork
{
    void Commit();
}

IUnitOfWork implementation:

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

这篇关于错误:确保控制器有一个无参数的公共构造函数webapi的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆