Asegúrese de que el controlador tenga un error de constructor público sin parámetros

He seguido este tutorial que funcionó muy bien, hasta que modifiqué mi DbContext para tener un constructor adicional. Ahora estoy teniendo problemas con la resolución y no estoy seguro de qué hacer para solucionar esto. ¿Hay alguna manera fácil de forzarlo para que agarre el constructor sin parámetros o me estoy acercando a esto incorrectamente?

DbContext con dos constructores:

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

Constructor SiteController :

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

Repositorio:

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

Error de la llamada de WebApi:

System.InvalidOperationException: Se produjo un error al intentar crear un controlador de tipo ‘SiteController’. Asegúrese de que el controlador tenga un constructor público sin 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: escriba ‘Dashboard.Web.Controllers.SiteController’ no tiene un constructor predeterminado.

 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) 

El tutorial fue excelente y funcionó bien hasta que agregué el segundo constructor.

Lo que está sucediendo es que estás mordido por este problema . Básicamente, lo que sucedió es que no registraste tus controladores explícitamente en tu contenedor. Unity intenta resolver los tipos de concreto no registrados para usted, pero como no puede resolverlo (causado por un error en su configuración), devuelve nulo. Se lo fuerza a devolver nulo, porque la API web lo obliga a hacerlo debido al contrato IDependencyResolver . Como Unity devuelve nulo, Web API intentará crear el controlador en sí mismo, pero como no tiene un constructor predeterminado lanzará la excepción “Asegúrese de que el controlador tenga un constructor público sin parámetros”. Este mensaje de excepción es engañoso y no explica la causa real.

Habría visto un mensaje de excepción mucho más claro si registró sus controladores explícitamente, y es por eso que siempre debe registrar todos los tipos de raíz de forma explícita.

Pero, por supuesto, el error de configuración proviene de que usted agregue el segundo constructor a su DbContext . Unity siempre intenta elegir el constructor con más argumentos, pero no tiene idea de cómo resolver este constructor en particular.

Entonces, la verdadera causa es que está tratando de usar las capacidades de auto-cableado de Unity para crear el DbContext . DbContext es un tipo especial que no se debe DbContext . Es un tipo de marco y, por lo tanto, debe retroceder para registrarlo utilizando un delegado de fábrica :

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

En mi caso, fue por una excepción dentro del constructor de mi dependencia inyectada (en tu ejemplo, dentro del constructor de DashboardRepository). La excepción fue capturada en algún lugar dentro de la infraestructura de MVC. Encontré esto después de que agregué registros en lugares relevantes.

A veces, debido a que está resolviendo su interfaz en ContainerBootstraper.cs, es muy difícil detectar el error. En mi caso, hubo un error al resolver la implementación de la interfaz que he inyectado al controlador api. No pude encontrar el error porque he resuelto la interfaz en mi bootstraperContainer de la siguiente manera: container.RegisterType(new ContainerControlledLifetimeManager());
luego agregué la siguiente línea en mi contenedor de bootstrap: container.RegisterType(); así que cuando compilo el proyecto, el comstackdor se quejó y se detuvo en la línea superior y mostró el error.

Tuve el mismo problema y lo resolví haciendo cambios en el archivo UnityConfig.cs Para resolver el problema de dependencia en el archivo UnityConfig.cs que debe agregar:

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

Yo tuve el mismo problema. Lo busqué en Google durante dos días. Por fin, noté accidentalmente que el problema era el modificador de acceso del constructor del controlador. No puse la palabra clave public detrás del constructor del controlador.

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

Agrego esta experiencia como otra respuesta, tal vez alguien más cometió un error similar.