ASP.NET कोर निर्भरता इंजेक्शन त्रुटि: सक्रिय करने का प्रयास करते समय प्रकार के लिए सेवा को हल करने में असमर्थ


195

मैंने एक .NET कोर MVC एप्लिकेशन बनाया और अपने नियंत्रक के लिए एक रिपॉजिटरी को इंजेक्ट करने के लिए डिपेंडेंसी इंजेक्शन और रिपॉजिटरी पैटर्न का उपयोग किया। हालाँकि, मुझे एक त्रुटि मिल रही है:

InvalidOperationException: 'WebApplication1.Controllers.BlogController' को सक्रिय करने का प्रयास करते हुए टाइप 'WebApplication1.Data.BloggerRepository' के लिए सेवा को हल करने में असमर्थ।

मॉडल (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; }
    }
}

रिपोजिटरी (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 (प्रासंगिक कोड)

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

नियंत्रक (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);
        }
    }
}

मुझे यकीन नहीं है कि मैं क्या गलत कर रहा हूं। कोई विचार?


मुझे पता है कि यह एक पुराना सवाल है, लेकिन ... आपको किसी सेवा के अंदर db संदर्भ को नहीं छोड़ना चाहिए। Db सन्दर्भ स्वतः स्कोप रिज़ॉल्वर द्वारा निपटाया जाता है। यदि आप किसी सेवा के अंदर इसका निपटान करते हैं, तो इसे उसी अनुरोध / दायरे में अगली सेवा को कॉल करते समय निपटाया जा सकता है।
सिल्वरमाइंड

1
सुनिश्चित करें कि सेवा (अनुपस्थित वर्ग) को ddservices.AddTransient <YourClassOrInter>> (); (
मौरिसियो ग्रेसिया

जवाबों:


287

अपवाद कहता है कि यह सेवा को हल नहीं कर सकता है WebApplication1.Data.BloggerRepositoryक्योंकि आपके नियंत्रक पर निर्माता इंटरफ़ेस के बजाय कंक्रीट वर्ग के लिए पूछ रहा है। तो बस इसे बदलें:

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

6
कमाल है कि एक एकल चरित्र को अनदेखा करना कितना आसान है ... धन्यवाद!
jleach

क्या एक चैंपियन, HttpContextAccessorवर्ग का उपयोग करते हुए इसे IHttpContextAccessor
हटा

इसलिए चिढ़ गया क्योंकि मैंने इस पर 30 मिनट से अधिक समय तक कमर लगाई थी। मैक पर वीएस आपको आपको "अप्रत्याशित रूप से छोड़ दिया" त्रुटि देता है। सही त्रुटि प्राप्त करने के लिए टर्मिनल पर चलना है, तो मैं इस समाधान में टकरा गया।
NoloMokgosi

56

मैं इस समस्या में भाग गया क्योंकि निर्भरता इंजेक्शन सेटअप में मुझे एक रिपॉजिटरी की निर्भरता याद आ रही थी जो एक नियंत्रक की निर्भरता है:

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

मेरे लिए हल किया, यह मेरी समस्या थी
anisanwesley

मेरी समस्या का समाधान किया, क्योंकि मैंने पहचाना कि मेरी सेवाएं सही "नेमस्पेस" में नहीं थीं।
user2982195

24

मेरे मामले में मैं एक ऑब्जेक्ट के लिए निर्भरता इंजेक्शन करने की कोशिश कर रहा था जिसके लिए कंस्ट्रक्टर के तर्क की आवश्यकता थी। इस मामले में, स्टार्टअप के दौरान मैंने सिर्फ कॉन्फ़िगरेशन फ़ाइल से तर्क दिए, उदाहरण के लिए:

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

18

मुझे एक अलग समस्या हो रही थी, और हाँ, मेरे नियंत्रक के लिए मानकीकृत निर्माता पहले से ही सही इंटरफ़ेस के साथ जोड़ा गया था। मैंने जो किया वह कुछ सीधा था। मैं बस अपनी startup.csफ़ाइल पर जाता हूं , जहां मुझे पंजीकरण विधि के लिए एक कॉल दिखाई दे सकती है।

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

मेरे मामले में, यह Registerविधि एक अलग वर्ग में थी Injector। इसलिए मुझे अपने नए शुरू किए गए इंटरफेसेस को वहां जोड़ना पड़ा।

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

यदि आप देखते हैं, तो इस फ़ंक्शन का पैरामीटर है this IServiceCollection

उम्मीद है की यह मदद करेगा।


यह वह है जिसे मैं जोड़ना भूल गया। मुझे सेवा में इंजेक्टर का संदर्भ नहीं मिला। की जरूरत है .AddTransient <> (); आप लोगों को धन्यवाद!
ओमजीग

14

केवल अगर किसी की मेरे जैसी ही स्थिति है, तो मैं मौजूदा डेटाबेस के साथ EntityFramework का एक ट्यूटोरियल कर रहा हूं, लेकिन जब मॉडल डेटाबेस पर नया डेटाबेस संदर्भ बनाया जाता है, तो हमें स्टार्टअप में संदर्भ को अपडेट करने की आवश्यकता है, लेकिन केवल सेवाओं में नहीं। AddDbContext लेकिन AddIdentity भी अगर आपके पास उपयोगकर्ता प्रमाणीकरण है

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

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

7

आपको एक नई सेवा जोड़ने की आवश्यकता है DBcontext स्टार्टअप में

चूक

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

इसे जोड़ो

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


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

आप स्टार्टअप ConfigureServicesविधि में "services.AddScoped" जोड़ना भूल गए ।


5

मुझे यह मुद्दा एक मूर्खतापूर्ण गलती के कारण मिला। मैं ASP.NET कोर अनुप्रयोग में नियंत्रकों की खोज करने के लिए अपनी सेवा कॉन्फ़िगरेशन प्रक्रिया को हुक करना भूल गया था।

इस विधि को जोड़ने से इसे हल किया गया:

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

5

मुझे काम करने के लिए इस लाइन को कन्फिगर्स सर्विसेज में जोड़ना था।

services.AddSingleton<IOrderService, OrderService>();

3

मैं नीचे अपवाद हो रहा था

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

चूँकि मैं DbContext व्युत्पन्न वर्ग IBlogContextFactory के उदाहरण बनाने के लिए रजिस्टर फैक्ट्री चाहता था और Blog Conxt के इंस्टेंस को तुरंत बनाने के लिए विधि का उपयोग करता हूं ताकि मैं निर्भरता इंजेक्शन के साथ पैटर्न के नीचे उपयोग कर सकूं और यूनिट परीक्षण के लिए जॉकिंग का भी उपयोग कर सकूं।

पैटर्न मैं उपयोग करना चाहता था

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

लेकिन नए BloggingContext () के बजाय मैं BlogController वर्ग के नीचे के रूप में निर्माता के माध्यम से कारखाने इंजेक्षन करना चाहता हूं

    [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;
    }
}

यहाँ मेरा सेवा पंजीकरण कोड है

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

और नीचे मेरे मॉडल और कारखाने वर्ग हैं

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

----- .net कोर एमवीसी परियोजना में इसे ठीक करने के लिए - मैंने निर्भरता पंजीकरण पर परिवर्तन नीचे किया था

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

संक्षेप में .net कोर डेवलपर फ़ैक्टरी फ़ंक्शन को इंजेक्ट करने के लिए ज़िम्मेदार है, जो यूनिटी और .नेट फ्रेमवर्क के मामले में ध्यान रखा गया था।


3

यह समस्या इसलिए है क्योंकि आपने इसके लिए लिखे इंटरफ़ेस के साथ डेटा एक्सेस घटक को पंजीकृत नहीं किया था। निम्नानुसार उपयोग करके देखें

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

2

यदि आप AutoFac का उपयोग कर रहे हैं और इस त्रुटि को प्राप्त कर रहे हैं, तो आपको उस सेवा को निर्दिष्ट करने के लिए "As" कथन जोड़ना चाहिए जो ठोस कार्यान्वयन लागू करता है।

अर्थात। आपको लिखना चाहिए:

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

के बजाय

containerBuilder.RegisterType<DataService>();

2

ओह, थैंक्यू @kimbaudi, मैंने इस tuts का अनुसरण किया

https://dotnettutorials.net/lesson/generic-repository-pattern-csharp-mvc/

और आपकी जैसी त्रुटि हुई। लेकिन आपके कोड को पढ़ने के बाद मुझे पता चला कि मेरा समाधान जोड़ रहा था

सेवाओं। उन्नत (IGenericRepository, GenericRepository);

StartUp.cs फ़ाइल में कॉन्फ़िगर विधि सेवा =))


1

सेवाएं जोड़ें ।dd.Singleton (); अपने प्रोजेक्ट के Startup.cs फ़ाइल के कॉन्फिगरस्वाइस विधि में।

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

अधिक जानकारी के लिए कृपया इस URL पर जाएँ: https://www.youtube.com/watch?v=aMjiiWtfj2M

सभी तरीकों के लिए (अर्थात AddSingleton बनाम AddScoped बनाम AddTransient) कृपया इस URL पर जाएं : https://www.youtube.com/watch?v=v6Nr7Zman_Y&list=PL6n9fhu94yyVkdrusLaQsfERmL_Jh4XmU&index=44 )


1

मेरे पास एक ही मुद्दा था और यह पता चला कि मेरा कोड इंजेक्शन से पहले इसका उपयोग कर रहा था।

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

मुझे पता है कि इसका सवाल से कोई लेना-देना नहीं है, लेकिन जब से मुझे इस पृष्ठ पर भेजा गया है, मैं इसे किसी और के लिए उपयोगी मानता हूं।


1

वर्ग कोड तक पहुंचने से पहले ही एक सेवा का समाधान किया जाता है, इसलिए हमें अपने निर्भरता इंजेक्शन की जांच करने की आवश्यकता है।

मेरे मामले में मैंने जोड़ा

        services.AddScoped<IMeasurementService, MeasurementService>();

StartupExtensions.cs में


0

मैंने प्रतिस्थापित किया

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

साथ में

services.AddTransient<IMyLogger, MyLogger>();

और इसने मेरे लिए काम किया।


-1

मुझे यह त्रुटि मिली क्योंकि मैंने उस प्रकार का एक चर (कॉन्फिगर सर्विसेज सेवा के ऊपर) घोषित किया था जो मेरा संदर्भ था। मैं था:

CupcakeContext _ctx

यकीन नहीं होता कि मैं क्या सोच रहा था। मुझे पता है कि यह करने के लिए कानूनी है अगर आपके पैरामीटर को कॉन्फ़िगर करने की विधि में।


-1

मुझे त्रुटि मिली: ".net कोर के सभी संस्करणों के लिए निर्भरता xxxxxxxx को हल करने में असमर्थ"। मैंने इंटरनेट पर उपलब्ध हर चीज की कोशिश की और दिनों तक अटका रहा। एकमात्र समाधान जो मैं लेकर आया था, वह परियोजना में nuget.config फ़ाइल जोड़ रहा था और फिर इसे काम करने के लिए डॉटनेट पुनर्स्थापना का उपयोग कर रहा था।

Nuget.config फ़ाइल की सामग्री:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="AspNetCore" value="https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json" />
    <add key="AspNetCoreTools" value="https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json" />
    <add key="NuGet" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.