ASP.NET Core依赖注入错误:尝试激活时无法解析类型的服务


195

我创建了一个.NET Core 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上下文。如果将其放在服务中,则在同一请求/作用域中调用下一个服务时,可能会将其处置。
Silvermind

1
确保使用“ services.AddTransient <YourClassOrInterface>();”添加了服务(缺少类);
Mauricio Gracia Gutierrez

Answers:


287

异常表示无法解决该服务,WebApplication1.Data.BloggerRepository因为控制器上的构造函数正在请求具体的类而不是接口。因此,只需更改以下内容:

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

6
忽略一个字符有多么容易...谢谢!
jleach

HttpContextAccessor上课时收到冠军的冠军证明我需要IHttpContextAccessor
mtbennett

太恼火了,因为我在此上腰了30多分钟。Mac上最差的VS给您“ Donet意外退出”错误。必须在终端上运行以获取正确的错误,然后我碰到了这个解决方案。
NoloMokgosi

56

我遇到了这个问题,因为在依赖项注入设置中,我缺少存储库的依赖项,而该存储库是控制器的依赖项:

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

为我解决了,这是我的问题
anisanwesley19年

解决了我的问题,因为我认识到我的服务不在正确的“名称空间”中。
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

希望这可以帮助。


这是我忘记添加的内容。我错过了对该服务的Injector参考。需要.AddTransient <>(); 感谢你们!
Omzig

14

只有在任何人都和我一样的情况下,我才会使用现有数据库进行EntityFramework的教程,但是当在models文件夹上创建新数据库上下文时,我们需要在启动时更新上下文,而不仅是在服务中。如果您具有用户身份验证,也可以使用AddDbContext但可以使用AddIdentity

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

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


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

您忘记了在启动ConfigureServices方法中添加“ services.AddScoped” 。


5

由于一个很愚蠢的错误,我遇到了这个问题。我忘记了挂钩服务配置过程以在ASP.NET Core应用程序中自动发现控制器。

添加此方法可以解决该问题:

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

5

我必须在ConfigureServices中添加此行才能工作。

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

因为我想注册Factory来创建DbContext派生类IBlogContextFactory的实例,并使用Create方法实例化Blog Context的实例,所以我可以将以下模式与依赖关系注入一起使用,也可以将模拟用于单元测试。

我想使用的模式是

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 Core MVC项目中解决此问题-我在依赖项注册上做了以下更改

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

简而言之,.net核心开发人员负责注入工厂功能,在使用Unity和.Net Framework的情况下,这些功能得到了照顾。



2

如果使用的是AutoFac并出现此错误,则应添加“ As”语句以指定具体实现所实现的服务。

就是 您应该写:

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

代替

containerBuilder.RegisterType<DataService>();


1

添加服务。AddSingleton(); 在项目的Startup.cs文件的ConfigureServices方法中。

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=PL6n9fhu94yhVkdrusLaQsfERmL_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

我收到此错误是因为我声明了一个变量(在ConfigureServices方法之上),它是我的上下文。我有:

CupcakeContext _ctx

不知道我在想什么。我知道,如果您将参数传递给Configure方法,则这样做是合法的。


-1

我收到错误:“无法为所有版本的.net core解决依赖项xxxxxxxx”。我尝试了互联网上所有可用的东西,并且被困了好几天。我想出的唯一解决方案是在项目中添加nuget.config文件,然后使用dotnet restore使它工作。

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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.