Certifique-se de que o controlador tenha um erro de construtor público sem parâmetros

Eu segui este tutorial que funcionou muito bem, até que eu modifiquei meu DbContext para ter um construtor adicional. Agora estou tendo problemas com a resolução e não sei o que fazer para corrigir isso. Existe uma maneira fácil de forçá-lo para pegar o construtor sem parâmetros ou estou abordando isso incorretamente?

DbContext com dois construtores:

 public class DashboardDbContext : DbContext { public DashboardDbContext() : base("DefaultConnection") { } public DashboardDbContext(DbConnection dbConnection, bool owns) : base(dbConnection, owns) { } } 

Construtor SiteController :

 private readonly IDashboardRepository _repo; public SiteController(IDashboardRepository repo) { _repo = repo; } 

Repositório:

 DashboardDbContext _context; public DashboardRepository(DashboardDbContext context) { _context = context; } 

Código 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 GetServices(Type serviceType) { try { return _container.ResolveAll(serviceType); } catch (ResolutionFailedException) { return new List(); } } public IDependencyScope BeginScope() { var child = _container.CreateChildContainer(); return new UnityResolver(child); } public void Dispose() { _container.Dispose(); } } 

WebApiConfig:

 var container = new UnityContainer(); container.RegisterType(new HierarchicalLifetimeManager()); config.DependencyResolver = new UnityResolver(container); 

Erro da chamada do WebApi:

System.InvalidOperationException: Ocorreu um erro ao tentar criar um controlador do tipo ‘SiteController’. Certifique-se de que o controlador tenha um construtor público sem parâmetros.

 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.d__0.MoveNext() 

InnerException: System.ArgumentException: Digite ‘Dashboard.Web.Controllers.SiteController’ não tem um construtor padrão.

 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) 

O tutorial foi ótimo e tem funcionado bem para mim até eu adicionar o segundo construtor.

O que está acontecendo é que você é mordido por esse problema . Basicamente, o que aconteceu é que você não registrou seus controladores explicitamente em seu contêiner. Unity tenta resolver tipos de concreto não registrados para você, mas como não pode resolvê-lo (causado por um erro em sua configuração), ele retorna null. Ele é forçado a retornar null, porque o Web API o obriga a fazê-lo devido ao contrato IDependencyResolver . Como o Unity retorna null, a API da Web tentará criar o próprio controlador, mas como ele não possui um construtor padrão, ele emitirá a exceção “Certifique-se de que o controlador tenha um construtor público sem parâmetros”. Essa mensagem de exceção é enganosa e não explica a causa real.

Você teria visto uma mensagem de exceção muito mais clara se registrasse seus controllers explicitamente, e é por isso que você deve sempre registrar todos os tipos de root explicitamente.

Mas, claro, o erro de configuração vem de você adicionar o segundo construtor ao seu DbContext . Unity sempre tenta escolher o construtor com mais argumentos, mas não tem idéia de como resolver esse construtor em particular.

Portanto, a causa real é que você está tentando usar os resources de fiação automática do Unity para criar o DbContext . DbContext é um tipo especial que não deve ser conectado automaticamente. É um tipo de estrutura e, portanto, você deve fazer um backup usando um delegado de fábrica :

 container.Register( new InjectionFactory(c => new DashboardDbContext())); 

No meu caso, foi por causa da exceção dentro do construtor da minha dependência injetada (no seu exemplo – dentro do construtor DashboardRepository). A exceção foi capturada em algum lugar dentro da infraestrutura do MVC. Eu encontrei isso depois que eu adicionei logs em locais relevantes.

Às vezes, porque você está resolvendo sua interface no ContainerBootstraper.cs, é muito difícil detectar o erro. No meu caso, houve um erro na resolução da implementação da interface que eu injetei no controlador da API. Não consegui encontrar o erro porque resolvi a interface no meu bootstraperContainer da seguinte forma: container.RegisterType(new ContainerControlledLifetimeManager());
então eu adicionei a seguinte linha no meu contêiner de bootstrap: container.RegisterType(); então quando eu compilo o projeto, o compilador reclamou e parou na linha acima e mostrou o erro.

Eu tive o mesmo problema e resolvi fazendo alterações no arquivo UnityConfig.cs Para resolver o problema de dependência no arquivo UnityConfig.cs, você precisa adicionar:

 public static void RegisterComponents() { var container = new UnityContainer(); container.RegisterType(); DependencyResolver.SetResolver(new UnityDependencyResolver(container)); } 

Eu tive o mesmo problema. Eu pesquisei por dois dias. Por fim, notei acidentalmente que o problema era o modificador de access do construtor do Controlador. Eu não coloquei a palavra-chave public por trás do construtor do Controlador.

 public class MyController : ApiController { private readonly IMyClass _myClass; public MyController(IMyClass myClass) { _myClass = myClass; } } 

Acrescentei essa experiência como outra resposta, talvez alguém tenha cometido um erro semelhante.