479 votes

Erreur ASP.NET Core Dependency Injection : Impossible de résoudre le service pour le type lors de la tentative d'activation.

J'ai créé une application .NET Core MVC et j'utilise l'injection de dépendances et le modèle de référentiel pour injecter un référentiel dans mon contrôleur. Cependant, je reçois une erreur :

InvalidOperationException : Impossible de résoudre le service de type 'WebApplication1.Data.BloggerRepository' lors de la tentative d'activation de 'WebApplication1.Controllers.BlogController'.

Modèle (Blog.cs)

namespace WebApplication1.Models
{
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
    }
}

DbContext (BloggingContext.cs)

using Microsoft.EntityFrameworkCore;
using WebApplication1.Models;

namespace WebApplication1.Data
{
    public class BloggingContext : DbContext
    {
        public BloggingContext(DbContextOptions<BloggingContext> options)
            : base(options)
        { }
        public DbSet<Blog> Blogs { get; set; }
    }
}

Référentiel (IBloggerRepository.cs & BloggerRepository.cs)

using System;
using System.Collections.Generic;
using WebApplication1.Models;

namespace WebApplication1.Data
{
    internal interface IBloggerRepository : IDisposable
    {
        IEnumerable<Blog> GetBlogs();

        void InsertBlog(Blog blog);

        void Save();
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using WebApplication1.Models;

namespace WebApplication1.Data
{
    public class BloggerRepository : IBloggerRepository
    {
        private readonly BloggingContext _context;

        public BloggerRepository(BloggingContext context)
        {
            _context = context;
        }

        public IEnumerable<Blog> GetBlogs()
        {
            return _context.Blogs.ToList();
        }

        public void InsertBlog(Blog blog)
        {
            _context.Blogs.Add(blog);
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        private bool _disposed;

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _context.Dispose();
                }
            }
            _disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}

Startup.cs (code pertinent)

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<BloggingContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddScoped<IBloggerRepository, BloggerRepository>();

    services.AddMvc();

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
}

Contrôleur (BlogController.cs)

using System.Linq;
using Microsoft.AspNetCore.Mvc;
using WebApplication1.Data;
using WebApplication1.Models;

namespace WebApplication1.Controllers
{
    public class BlogController : Controller
    {
        private readonly IBloggerRepository _repository;

        public BlogController(BloggerRepository repository)
        {
            _repository = repository;
        }

        public IActionResult Index()
        {
            return View(_repository.GetBlogs().ToList());
        }

        public IActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create(Blog blog)
        {
            if (ModelState.IsValid)
            {
                _repository.InsertBlog(blog);
                _repository.Save();
                return RedirectToAction("Index");
            }
            return View(blog);
        }
    }
}

Je ne suis pas sûr de ce que je fais de mal. Vous avez des idées ?

825voto

DavidG Points 12762

L'exception dit qu'elle ne peut pas résoudre le service pour WebApplication1.Data.BloggerRepository parce que le constructeur de votre contrôleur demande la classe concrète au lieu de l'interface. Donc, il suffit de changer ça :

public BlogController(IBloggerRepository repository)
//                    ^
//                    Add this!
{
    _repository = repository;
}

105voto

hsop Points 1015

J'ai rencontré ce problème parce que dans la configuration de l'injection de dépendances, il me manquait une dépendance d'un référentiel qui est une dépendance d'un contrôleur :

services.AddScoped<IDependencyOne, DependencyOne>();    <-- I was missing this line!
services.AddScoped<IDependencyTwoThatIsDependentOnDependencyOne, DependencyTwoThatIsDependentOnDependencyOne>();

44voto

Sean Points 319

Dans mon cas, j'essayais de faire une injection de dépendance pour un objet qui nécessitait des arguments de constructeur. Dans ce cas, pendant le démarrage, j'ai juste fourni les arguments du fichier de configuration, par exemple :

var config = Configuration.GetSection("subservice").Get<SubServiceConfig>();
services.AddScoped<ISubService>(provider => new SubService(config.value1, config.value2));

33voto

Sibeesh Venu Points 4473

J'avais un problème différent, et oui le constructeur paramétré pour mon contrôleur était déjà ajouté avec l'interface correcte. Ce que j'ai fait est quelque chose de simple. Je vais juste dans mon startup.cs où j'ai pu voir un appel à la méthode d'enregistrement.

public void ConfigureServices(IServiceCollection services)
{
   services.Register();
}

Dans mon cas, cela Register était dans une classe séparée Injector . J'ai donc dû y ajouter mes interfaces nouvellement introduites.

public static class Injector
{
    public static void Register(this IServiceCollection services)
    {
        services.AddTransient<IUserService, UserService>();
        services.AddTransient<IUserDataService, UserDataService>();
    }
}

Si vous voyez, le paramètre de cette fonction est this IServiceCollection

J'espère que cela vous aidera.

20voto

Adrian Points 59

Seulement si quelqu'un a la même situation que moi, je fais un tutoriel d'EntityFramework avec une base de données existante, mais quand le nouveau contexte de base de données est créé sur les dossiers modèles, nous devons mettre à jour le contexte au démarrage, mais pas seulement dans services.AddDbContext mais aussi AddIdentity si vous avez l'authentification des utilisateurs.

services.AddDbContext<NewDBContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<NewDBContext>()
                .AddDefaultTokenProviders();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X