Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core Dependency Injection error: Unable to resolve service for type while attempting to activate

I created an .NET Core MVC application and use Dependency Injection and Repository Pattern to inject a repository to my controller. However, I am getting an error:

InvalidOperationException: Unable to resolve service for type 'WebApplication1.Data.BloggerRepository' while attempting to activate 'WebApplication1.Controllers.BlogController'.

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

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

I'm not sure what I'm doing wrong. Any ideas?

like image 283
kimbaudi Avatar asked Nov 30 '16 23:11

kimbaudi


People also ask

What is difference between Addtransient and Addscoped and Addsingleton?

Singleton is a single instance for the lifetime of the application domain. Scoped is a single instance for the duration of the scoped request, which means per HTTP request in ASP.NET. Transient is a single instance per code request.

What is IServiceCollection in .NET core?

} IServiceCollection is the collection of the service descriptors. We can register our services in this collection with different lifestyles (Transient, scoped, singleton) IServiceProvider is the simple built-in container that is included in ASP.NET Core that supports constructor injection by default.

What is injection dependency C#?

Dependency Injection (DI) is a software design pattern that allows us to develop loosely coupled code. DI is a great way to reduce tight coupling between software components. DI also enables us to better manage future changes and other complexity in our software. The purpose of DI is to make code maintainable.

Can not consume scoped service from Singleton?

You should almost never consume scoped service or transient service from a singleton. You should also avoid consuming transient service from a scoped service. What is happening when you consume scoped service from a singleton service is known as a captive dependency.


1 Answers

To break down the error message:

Unable to resolve service for type 'WebApplication1.Data.BloggerRepository' while attempting to activate 'WebApplication1.Controllers.BlogController'.

That is saying that your application is trying to create an instance of BlogController but it doesn't know how to create an instance of BloggerRepository to pass into the constructor.

Now look at your startup:

services.AddScoped<IBloggerRepository, BloggerRepository>(); 

That is saying whenever a IBloggerRepository is required, create a BloggerRepository and pass that in.

However, your controller class is asking for the concrete class BloggerRepository and the dependency injection container doesn't know what to do when asked for that directly.

I'm guessing you just made a typo, but a fairly common one. So the simple fix is to change your controller to accept something that the DI container does know how to process, in this case, the interface:

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

Note that some objects have their own custom ways to be registered, this is more common when you use external Nuget packages, so it pays to read the documentation for them. For example if you got a message saying:

Unable to resolve service for type 'Microsoft.AspNetCore.Http.IHttpContextAccessor' ...

Then you would fix that using the custom extension method provided by that library which would be:

services.AddHttpContextAccessor(); 

For other packages - always read the docs.

like image 141
DavidG Avatar answered Sep 19 '22 13:09

DavidG