确保控制器具有无参数的公共构造函数错误

sca*_*cci 93 c# asp.net-mvc unity-container asp.net-web-api

我已经按照本教程进行了很好的工作,直到我修改了我DbContext有一个额外的构造函数.我现在遇到了解决方案的问题,不知道如何解决这个问题.是否有一种简单的方法可以强制它抓住无参数构造函数,或者我接近这个错误?

DbContext 有两个构造函数:

public class DashboardDbContext : DbContext
{
    public DashboardDbContext() : base("DefaultConnection") { }

    public DashboardDbContext(DbConnection dbConnection, bool owns)
        : base(dbConnection, owns) { }
}
Run Code Online (Sandbox Code Playgroud)

SiteController 构造函数:

private readonly IDashboardRepository _repo;

public SiteController(IDashboardRepository repo)
{
    _repo = repo;
}
Run Code Online (Sandbox Code Playgroud)

库:

DashboardDbContext _context;

public DashboardRepository(DashboardDbContext context)
{
    _context = context;
}
Run Code Online (Sandbox Code Playgroud)

UnityResolver 码:

public class UnityResolver : IDependencyResolver
{
    private readonly IUnityContainer _container;

    public UnityResolver(IUnityContainer container)
    {
        _container = container;
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return _container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return _container.ResolveAll(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        var child = _container.CreateChildContainer();
        return new UnityResolver(child);
    }

    public void Dispose()
    {
        _container.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

WebApiConfig:

var container = new UnityContainer();
container.RegisterType<IDashboardRepository, DashboardRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
Run Code Online (Sandbox Code Playgroud)

WebApi调用出错:

System.InvalidOperationException:尝试创建"SiteController"类型的控制器时发生错误.确保控制器具有无参数的公共构造函数.

at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) 
at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request) 
at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken) 
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()
Run Code Online (Sandbox Code Playgroud)

InnerException:System.ArgumentException:Type'Dashboard.Web.Controllers.SiteController'没有默认构造函数.

at System.Linq.Expressions.Expression.New(Type type) 
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) 
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) 
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
Run Code Online (Sandbox Code Playgroud)

该教程非常棒,并且在我添加第二个构造函数之前一直很好用.

Ste*_*ven 120

发生的事情是你被这个问题所困扰.基本上,发生的事情是您没有在容器中明确注册控制器.Unity尝试为您解析未注册的具体类型,但由于它无法解析它(由配置中的错误引起),因此它返回null.它被强制返回null,因为Web API强制它由于IDependencyResolver合同而这样做.由于Unity返回null,Web API将尝试创建控制器本身,但由于它没有默认构造函数,因此它将抛出"确保控制器具有无参数公共构造函数"异常.此异常消息具有误导性,并不能解释真正的原因.

如果您明确注册了控制器,您会看到更清晰的异常消息,这就是您应该始终明确注册所有根类型的原因.

但是,当然,配置错误来自于将第二个构造函数添加到您的DbContext.Unity总是试图选择具有最多参数的构造函数,但它不知道如何解析这个特定的构造函数.

所以真正的原因是你正在尝试使用Unity的自动连线功能来创建DbContext.DbContext是一种不应自动连线的特殊类型.它是一种框架类型,因此您应该回退使用工厂委托注册它:

container.Register<DashboardDbContext>(
    new InjectionFactory(c => new DashboardDbContext())); 
Run Code Online (Sandbox Code Playgroud)


Ill*_*dan 42

在我的情况下,这是因为我注入的依赖项的构造函数内部的异常(在您的示例中 - 在DashboardRepository构造函数内).这个例外是在MVC基础设施内部捕获的.我在相关地方添加了日志后发现了这一点.

  • 这是一个非常重要的答案.当看到"确保控制器具有无参数的公共构造函数"时,很容易陷入追逐Unity的设置问题的陷阱.但很可能设置了依赖关系,但是已经停止了一个异常的例外它正在解决. (5认同)
  • 这个.一百万次!我忘了在我的Ninject配置中添加依赖关系图. (2认同)

Ami*_*978 5

有时,因为您正在解析 ContainerBootstraper.cs 中的接口,所以很难捕获错误。就我而言,在解析我注入 api 控制器的接口的实现时出现错误。我找不到错误,因为我已经像这样解析了 bootstraperContainer 中的接口: container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
然后我在引导容器中添加了以下行: container.RegisterType<MyController>(); 所以当我编译项目时,编译器抱怨并在上面的行中停止并显示错误。


小智 5

我有同样的问题,我通过在UnityConfig.cs文件中进行更改来解决它为了解决UnityConfig.cs文件中的依赖性问题,您必须添加:

public static void RegisterComponents()    
{
    var container = new UnityContainer();
    container.RegisterType<ITestService, TestService>();
    DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
Run Code Online (Sandbox Code Playgroud)


Bob*_*obs 5

我有同样的问题。我用谷歌搜索了两天。最后我无意中注意到问题是Controller的构造函数的访问修饰符。我没有把public关键字放在 Controller 的构造函数后面。

public class MyController : ApiController
    {
        private readonly IMyClass _myClass;

        public MyController(IMyClass myClass)
        {
            _myClass = myClass;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我将此经历添加为另一个答案,也许其他人也犯了类似的错误。