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 BlogController
te maken, maar het weet niet hoe een exemplaar van BloggerRepository
om in de constructor te gaan.
Kijk nu naar uw startup:
services.AddScoped<IBloggerRepository, BloggerRepository>();
Dat zegt wanneer een IBloggerRepository
is vereist, maak een BloggerRepository
en pas dat in.
Uw controllerklasse vraagt echter om de betonklasse BloggerRepository
en 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 Register
methode 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 DBcontext
in 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& bellenlijst=pl6n9fhu94yhvkdruslaqsferml_jh4xmu&iverml_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 ConfigureServices
als 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