Error de inyección de dependencia: no se puede resolver el servicio para el tipo al intentar activarlo, mientras la clase está registrada
Creé una aplicación .NET Core MVC y utilicé la inyección de dependencia y el patrón de repositorio para inyectar un repositorio en mi controlador. Sin embargo, recibo un error:
InvalidOperationException: no se puede resolver el servicio para el tipo 'WebApplication1.Data.BloggerRepository' al intentar activar 'WebApplication1.Controllers.BlogController'.
Repositorio:
public interface IBloggerRepository { ... }
public class BloggerRepository : IBloggerRepository { ... }
Controlador:
public class BlogController : Controller
{
private readonly IBloggerRepository _repository;
public BlogController(BloggerRepository repository)
{
_repository = repository;
}
public IActionResult Index() { ... }
}
Inicio.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddScoped<IBloggerRepository, BloggerRepository>();
}
No estoy seguro de qué estoy haciendo mal. ¿Algunas ideas?
Para desglosar el mensaje de error:
No se puede resolver el servicio para el tipo 'WebApplication1.Data.BloggerRepository' al intentar activar 'WebApplication1.Controllers.BlogController'.
Es decir, su aplicación está intentando crear una instancia de BlogController
pero no sabe cómo crear una instancia BloggerRepository
para pasarla al constructor.
Ahora mira tu startup:
services.AddScoped<IBloggerRepository, BloggerRepository>();
Es decir, siempre que IBloggerRepository
se requiera a, cree a BloggerRepository
y páselo.
Sin embargo, su clase de controlador solicita la clase concreta BloggerRepository
y el contenedor de inyección de dependencia no sabe qué hacer cuando se le solicita directamente.
Supongo que acabas de cometer un error tipográfico, pero es bastante común. Entonces, la solución simple es cambiar su controlador para aceptar algo que el contenedor DI sepa cómo procesar, en este caso, la interfaz:
public BlogController(IBloggerRepository repository)
// ^
// Add this!
{
_repository = repository;
}
Tenga en cuenta que algunos objetos tienen sus propias formas personalizadas de registrarse; esto es más común cuando usa paquetes Nuget externos, por lo que vale la pena leer la documentación correspondiente. Por ejemplo, si recibe un mensaje que dice:
No se puede resolver el servicio para el tipo 'Microsoft.AspNetCore.Http.IHttpContextAccessor'...
Luego, lo solucionarías utilizando el método de extensión personalizado proporcionado por esa biblioteca, que sería:
services.AddHttpContextAccessor();
Para otros paquetes, lea siempre los documentos.
Me encontré con este problema porque en la configuración de inyección de dependencia me faltaba una dependencia de un repositorio que es una dependencia de un controlador:
services.AddScoped<IDependencyOne, DependencyOne>(); <-- I was missing this line!
services.AddScoped<IDependencyTwoThatIsDependentOnDependencyOne, DependencyTwoThatIsDependentOnDependencyOne>();
En mi caso, estaba intentando realizar una inyección de dependencia para un objeto que requería argumentos del constructor. En este caso, durante el inicio solo proporcioné los argumentos del archivo de configuración, por ejemplo:
var config = Configuration.GetSection("subservice").Get<SubServiceConfig>();
services.AddScoped<ISubService>(provider => new SubService(config.value1, config.value2));
Estaba teniendo un problema diferente y sí, el constructor parametrizado para mi controlador ya se agregó con la interfaz correcta. Lo que hice fue algo sencillo. Simplemente voy a mi startup.cs
archivo, donde pude ver una llamada al método de registro.
public void ConfigureServices(IServiceCollection services)
{
services.Register();
}
En mi caso, este Register
método estaba en una clase separada Injector
. Así que tuve que agregar allí mis interfaces recién introducidas.
public static class Injector
{
public static void Register(this IServiceCollection services)
{
services.AddTransient<IUserService, UserService>();
services.AddTransient<IUserDataService, UserDataService>();
}
}
Si ve, el parámetro de esta función esthis IServiceCollection
Espero que esto ayude.
Solo si alguien tiene la misma situación que yo, estoy haciendo un tutorial de EntityFramework con una base de datos existente, pero cuando se crea el nuevo contexto de la base de datos en las carpetas de modelos, necesitamos actualizar el contexto en el inicio, pero no solo en los servicios. AddDbContext pero AddIdentity también si tiene autenticación de usuarios
services.AddDbContext<NewDBContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<NewDBContext>()
.AddDefaultTokenProviders();