ASP.NET kernafhankelijkheid Injectiefout: Kan de service voor het type niet oplossen terwijl u probeert

Ik heb een .NET Core MVC-applicatie gemaakt en gebruik een afhankelijkheid injectie- en repository patroon om een ​​repository naar mijn controller te injecteren. Ik krijg echter een foutmelding:

InvalidOperationException: Kan de service voor Type ‘WebAppplication1.Data.bloggerrepository’ niet opgelost tijdens een poging om ‘WebAppplication1.controllers.blogcontroller’ te activeren.

model (blog.cs)

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

DBCONTEXT (bloggencontext.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; }
    }
}

Repository (iBlogGerrepository.cs & AMP; 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 (relevante code)

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

Controller (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);
        }
    }
}

Ik weet niet zeker wat ik verkeerd doe. Eventuele ideeën?


Antwoord 1, Autoriteit 100%

Om het foutbericht af te breken:

Niet in staat om service voor type ‘webapplication1.data.bloggerrepository’ op te lossen, terwijl u probeert te activeren ‘WebAppplication1.controllers.blogcontroller’.

Dat zegt dat uw aanvraag probeert een exemplaar van BlogControllerte maken, maar het weet niet hoe een exemplaar van BloggerRepositoryom in de constructor te gaan.

Kijk nu naar uw startup:

services.AddScoped<IBloggerRepository, BloggerRepository>();

Dat zegt wanneer een IBloggerRepositoryis vereist, maak een BloggerRepositoryen pas dat in.

Uw controllerklasse vraagt ​​echter om de betonklasse BloggerRepositoryen de afhankelijkheid Injectiecontainer weet niet wat u moet doen wanneer u dat rechtstreeks wordt gevraagd.

Ik vermoed dat je net een typfo hebt gemaakt, maar een vrij gebruikelijke. Dus de Simple Fix is ​​om uw controller te wijzigen om iets te accepteren dat de DI-container doet weet hoe u in dit geval kunt verwerken, in dit geval, de interface:

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

Merk op dat sommige objecten hun eigen aangepaste manieren hebben om geregistreerd te worden, dit komt vaker voor wanneer u externe Nuget-pakketten gebruikt, dus het loont om de documentatie voor hen te lezen. Bijvoorbeeld als u een bericht hebt gezegd:

Niet in staat om service voor type ‘Microsoft.aspnetcore.http.ihttpcontextaccessor’ …

op te lossen

Dan zou u opstellen dat het gebruik van de aangepaste verlengmethode verstrekt door die bibliotheek die zou zijn:

services.AddHttpContextAccessor();

Voor andere pakketten – lees altijd de documenten.


Antwoord 2, Autoriteit 18%

Ik heb dit probleem tegengekomen, omdat ik in de injectie-injectie-injectie van de afhankelijkheid een afhankelijkheid van een repository miste die een afhankelijkheid van een controller is:

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

Antwoord 3, autoriteit 7%

In mijn geval probeerde ik afhankelijkheidsinjectie uit te voeren voor een object waarvoor constructorargumenten nodig waren. In dit geval heb ik tijdens het opstarten zojuist de argumenten uit het configuratiebestand opgegeven, bijvoorbeeld:

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

Antwoord 4, autoriteit 6%

Ik had een ander probleem, en ja, de geparametriseerde constructor voor mijn controller was al toegevoegd met de juiste interface. Wat ik deed was iets eenvoudigs. Ik ga gewoon naar mijn startup.cs-bestand, waar ik een aanroep om te registreren methode kon zien.

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

In mijn geval zat deze Registermethode in een aparte klasse Injector. Dus ik moest mijn nieuw geïntroduceerde interfaces daar toevoegen.

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

Als je ziet, is de parameter voor deze functie this IServiceCollection

Hopelijk helpt dit.


Antwoord 5, autoriteit 3%

Alleen als iemand dezelfde situatie heeft als ik, doe ik een tutorial van EntityFramework met een bestaande database, maar wanneer de nieuwe databasecontext wordt gemaakt in de modelmappen, moeten we de context in het opstarten bijwerken, maar niet alleen in services.AddDbContext maar ook AddIdentity als je gebruikersauthenticatie hebt

services.AddDbContext<NewDBContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<NewDBContext>()
                .AddDefaultTokenProviders();

Antwoord 6, autoriteit 2%

U moet een nieuwe service toevoegen voor DBcontextin het opstarten

Standaard

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

Voeg dit toe

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

Antwoord 7, autoriteit 2%

Public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IEventRepository, EventRepository>();           
}

U bent vergeten “services.AddScoped” toe te voegen in de opstartmethode ConfigureServices.


Antwoord 8, autoriteit 2%

In mijn geval, .Net Core 3.0 API in
Startup.cs,
in methode

public void ConfigureServices(IServiceCollection services)

Ik moest toevoegen

services.AddScoped<IStateService, StateService>();

Antwoord 9, autoriteit 2%

Ik moest deze regel in ConfigureServices toevoegen om te kunnen werken.

services.AddSingleton<IOrderService, OrderService>();

Antwoord 10

Ik heb dit probleem gekregen door een nogal domme fout. Ik was vergeten mijn serviceconfiguratieprocedure vast te haken om controllers automatisch te ontdekken in de ASP.NET Core-toepassing.

Het toevoegen van deze methode loste het op:

// Add framework services.
            services.AddMvc()
                    .AddControllersAsServices();      // <---- Super important

Antwoord 11

Ik kwam onder de uitzondering

       System.InvalidOperationException: Unable to resolve service for type 'System.Func`1[IBlogContext]' 
        while attempting to activate 'BlogContextFactory'.\r\n at 
        Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, ISet`1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, ISet`1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, ISet`1 callSiteChain)\r\n at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType, ServiceProvider serviceProvider)\r\n at System.Collections.Concurrent.ConcurrentDictionaryExtensions.GetOrAdd[TKey, TValue, TArg] (ConcurrentDictionary`2 dictionary, TKey key, Func`3 valueFactory, TArg arg)\r\n at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)\r\n at Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)\r\n at lambda_method(Closure , IServiceProvider , Object[] )\r\n at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()

Omdat ik de fabriek wilde registreren om exemplaren van dbcontext-afgeleide klasse iBlogContextFactory te maken en gebruik methode te maken om te instantiëren van een blogcontext, zodat ik hieronder het patroon kan gebruiken samen met de afhankelijkheidsinjectie en kan ook spot gebruiken voor eenheidstests.

Het patroon dat ik wilde gebruiken is

public async Task<List<Blog>> GetBlogsAsync()
        {
            using (var context = new BloggingContext())
            {
                return await context.Blogs.ToListAsync();
            }
        }

Maar in plaats van nieuwe bloggencontext () wil ik de fabriek injecteren via constructor als in onderstaande blogcontroller-klasse

   [Route("blogs/api/v1")]
public class BlogController : ControllerBase
{
    IBloggingContextFactory _bloggingContextFactory;
    public BlogController(IBloggingContextFactory bloggingContextFactory)
    {
        _bloggingContextFactory = bloggingContextFactory;
    }
    [HttpGet("blog/{id}")]
    public async Task<Blog> Get(int id)
    {
        //validation goes here 
        Blog blog = null;
        // Instantiage context only if needed and dispose immediately
        using (IBloggingContext context = _bloggingContextFactory.CreateContext())
        {
            blog = await context.Blogs.FindAsync(id);
        }
        //Do further processing without need of context.
        return blog;
    }
}

Hier is mijn service-registratiecode

           services
            .AddDbContext<BloggingContext>()
            .AddTransient<IBloggingContext, BloggingContext>()
            .AddTransient<IBloggingContextFactory, BloggingContextFactory>();

en hieronder zijn mijn modellen en fabrieksklassen

   public interface IBloggingContext : IDisposable
{
    DbSet<Blog> Blogs { get; set; }
    DbSet<Post> Posts { get; set; }
}
public class BloggingContext : DbContext, IBloggingContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseInMemoryDatabase("blogging.db");
        //optionsBuilder.UseSqlite("Data Source=blogging.db");
    }
}
public interface IBloggingContextFactory
{
    IBloggingContext CreateContext();
}
public class BloggingContextFactory : IBloggingContextFactory
{
    private Func<IBloggingContext> _contextCreator;
    public BloggingContextFactory(Func<IBloggingContext> contextCreator)// This is fine with .net and unity, this is treated as factory function, but creating problem in .netcore service provider
    {
        _contextCreator = contextCreator;
    }
    public IBloggingContext CreateContext()
    {
        return _contextCreator();
    }
}
public class Blog
{
    public Blog()
    {
        CreatedAt = DateTime.Now;
    }
    public Blog(int id, string url, string deletedBy) : this()
    {
        BlogId = id;
        Url = url;
        DeletedBy = deletedBy;
        if (!string.IsNullOrWhiteSpace(deletedBy))
        {
            DeletedAt = DateTime.Now;
        }
    }
    public int BlogId { get; set; }
    public string Url { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime? DeletedAt { get; set; }
    public string DeletedBy { get; set; }
    public ICollection<Post> Posts { get; set; }
    public override string ToString()
    {
        return $"id:{BlogId} , Url:{Url} , CreatedAt : {CreatedAt}, DeletedBy : {DeletedBy}, DeletedAt: {DeletedAt}";
    }
}
public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

—– Om dit op te lossen in het .net Core MVC-project — ik heb onderstaande wijzigingen aangebracht in de afhankelijkheidsregistratie

           services
            .AddDbContext<BloggingContext>()
            .AddTransient<IBloggingContext, BloggingContext>()
            .AddTransient<IBloggingContextFactory, BloggingContextFactory>(
                    sp => new BloggingContextFactory( () => sp.GetService<IBloggingContext>())
                );

Kortom in .net kernontwikkelaar is verantwoordelijk voor het injecteren van de fabrieksfunctie, die in het geval van Unity en .Net Framework werd verzorgd.


Antwoord 12

Dit probleem wordt veroorzaakt doordat u de component voor gegevenstoegang niet hebt geregistreerd met de interface die ervoor is geschreven. Probeer het als volgt te gebruiken

services.AddTransient<IMyDataProvider, MyDataAccess>();`

Antwoord 13

Als u AutoFac gebruikt en deze fout krijgt, moet u een “As”-statement toevoegen om de service te specificeren die de concrete implementatie implementeert.

Dwz. je moet schrijven:

containerBuilder.RegisterType<DataService>().As<DataService>();

in plaats van

containerBuilder.RegisterType<DataService>();

Antwoord 14

Ohh, Bedank @kimbaudi, ik volgde deze tutjes

https://dotnettutorials.Net/lesson/generic-repository- PATROON-CSHARP-MVC /

en kreeg dezelfde fout als je. Maar na het lezen van uw code ontdekte ik dat mijn oplossing

toevoegt

Services.AddSCoped (IgenericRepository, GenericRepository);

In Configureservices -methode in Startup.cs File =))


Antwoord 15

Ik had hetzelfde probleem en ontdekte dat mijn code de injectie gebruikte voordat het werd geïnitialiseerd.

services.AddControllers(); // Will cause a problem if you use your IBloggerRepository in there since it's defined after this line.
services.AddScoped<IBloggerRepository, BloggerRepository>();

Ik weet dat het niets met de vraag te maken heeft, maar aangezien ik naar deze pagina is gestuurd, ontdek ik het mijn nuttig voor iemand anders.


Antwoord 16

Het oplossen van een service is gedaan, zelfs voordat de klassencode is bereikt, dus we moeten onze afhankelijkheid injecties controleren.

In mijn geval heb ik

toegevoegd

       services.AddScoped<IMeasurementService, MeasurementService>();

in startupexensions.cs


Antwoord 17

Misschien mis je dit:

services.AddScoped<IDependencyTwoThatIsDependentOnDependencyOne, DependencyTwoThatIsDependentOnDependencyOne>();

Antwoord 18

Voeg Services.AddSingleton () toe; in uw configureservices-methode van Startup.cs-bestand van uw project.

public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        // To register interface with its concrite type
        services.AddSingleton<IEmployee, EmployeesMockup>();
    }

Ga voor meer informatie naar deze URL: https://www.youtube.com/watch ? v = amjiiwtfj2m

Voor alle methoden (dwz addSingleton vs Addscoped vs adtransient) Bezoek deze URL: https://www.youtube.com/watch?v=v6nr7zman_y&amp bellenlijst=pl6n9fhu94yhvkdruslaqsferml_jh4xmu&ampiverml_jh4xmu&Index=44 )


Antwoord 19

Ik heb

vervangen

services.Add(new ServiceDescriptor(typeof(IMyLogger), typeof(MyLogger)));

met

services.AddTransient<IMyLogger, MyLogger>();

En het werkte voor mij.


Antwoord 20

Wijzig blogGerrepository naar iBlogGerrepository


Antwoord 21

Ik had problemen om te injecteren vanuit mijn programma.cs-bestand, met behulp van de CoopefaultBuilder zoals hieronder, maar uiteindelijk het opdagen door het standaardbinder over te slaan. (zie hieronder).

var host = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
    webBuilder.ConfigureServices(servicesCollection => { servicesCollection.AddSingleton<ITest>(x => new Test()); });
    webBuilder.UseStartup<Startup>();
}).Build();

Het lijkt erop dat de build binnen ConfigureWebHostDefaults had moeten worden gedaan om het werkend te krijgen, omdat anders de configuratie wordt overgeslagen, maar corrigeer me als ik het mis heb.

Deze aanpak werkte prima:

var host = new WebHostBuilder()
.ConfigureServices(servicesCollection =>
{
    var serviceProvider = servicesCollection.BuildServiceProvider();
    IConfiguration configuration = (IConfiguration)serviceProvider.GetService(typeof(IConfiguration));
    servicesCollection.AddSingleton<ISendEmailHandler>(new SendEmailHandler(configuration));
})
.UseStartup<Startup>()
.Build();

Dit laat ook zien hoe u een reeds vooraf gedefinieerde afhankelijkheid in .net core (IConfiguration) van

kunt injecteren


Antwoord 22

Voor mij werkte het om de DB-context in de ConfigureServicesals volgt toe te voegen:

services.AddDBContext<DBContextVariable>();

Antwoord 23

Ik ontving deze foutmelding waarbij ILoggergeïnjecteerdwerd in een .NET 5-klasse. Ik moest het klastype toevoegen om het te repareren.

ILogger-logger –> ILogger <MyClass>logger

Other episodes