Я создал приложение .NET Core MVC и использую шаблон впрыска и репозитория зависимостей для вливания репозитория в мой контроллер. Однако я получаю ошибку :
& gt; InvalidOperationException: Невозможно разрешить обслуживание для типа «WebApplication1.Data.BloggerRepository» при попытке активировать «WebApplication1.Controllers.BlogController».
Модель (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);
}
}
}
Я не уверен, что я делаю неправильно. Любые идеи?
Исключение говорит, что оно не может разрешить услугу для WebApplication1.Data.BloggerRepository
, потому что конструктор на вашем контроллере запрашивает конкретный класс вместо интерфейса. Так что просто измените это :
public BlogController(IBloggerRepository repository)
// ^
// Add this!
{
_repository = repository;
}
Я столкнулся с этой проблемой, потому что в настройке инъекции зависимостей мне не хватало зависимости хранилища, которая является зависимостью контроллера :
services.AddScoped<IDependencyOne, DependencyOne>(); <-- I was missing this line!
services.AddScoped<IDependencyTwoThatIsDependentOnDependencyOne, DependencyTwoThatIsDependentOnDependencyOne>();
В моем случае я пытался сделать инъекцию зависимости для объекта, который требовал аргументов конструктора. В этом случае во время запуска я просто предоставил аргументы из файла конфигурации, например:
var config = Configuration.GetSection("subservice").Get<SubServiceConfig>();
services.AddScoped<ISubService>(provider => new SubService(config.value1, config.value2));
Только если у кого-то такая же ситуация, как у меня, Я делаю учебник EntityFramework с существующей базой данных, но когда новый контекст базы данных создается в папках моделей, нам нужно обновить контекст в стартапе, но не только в сервисах. AddDbContext, но и AddIdentity, если у вас есть аутентификация пользователей
services.AddDbContext<NewDBContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<NewDBContext>()
.AddDefaultTokenProviders();
У меня была другая проблема, и да, параметризованный конструктор для моего контроллера уже был добавлен с правильным интерфейсом. То, что я сделал, было чем-то простым. Я просто перехожу к своему файлу startup.cs, где я могу увидеть метод вызова для регистрации.
public void ConfigureServices(IServiceCollection services)
{
services.Register();
}
В моем случае этот метод «Регистрация» был в отдельном классе «Инктор». Поэтому я должен был добавить свои недавно представленные интерфейсы там.
public static class Injector
{
public static void Register(this IServiceCollection services)
{
services.AddTransient<IUserService, UserService>();
services.AddTransient<IUserDataService, UserDataService>();
}
}
Если вы видите, параметром этой функции является this IServiceCollection
Надеюсь, это поможет.
Вам необходимо добавить новый сервис для DBcontext
при запуске
По умолчанию
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
Добавьте это
services.AddDbContext<NewDBContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("NewConnection")));
Я должен был добавить эту строку в ConfigureServices, чтобы работать.
services.AddSingleton<IOrderService, OrderService>();
Я получил эту проблему из-за довольно глупой ошибки. Я забыл подключить процедуру настройки службы, чтобы автоматически обнаруживать контроллеры в приложении ASP.NET Core.
Добавление этого метода решило это:
// Add framework services.
services.AddMvc()
.AddControllersAsServices(); // <---- Super important
ооо, спасибо @kimbaudi, я следовал за этим
https://dotnettutorials.net/lesson/generic-repository-pattern-csharp-mvc/
и получил ту же ошибку, что и ваш. Но после прочтения вашего кода я узнал, что мое решение добавляет
& Gt; services.AddScoped (IGenericRepository & lt; Todo & gt;, GenericRepository & lt; Todo & gt;) ;
в ConfigureServices метод в файле StartUp.cs =))
Public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IEventRepository, EventRepository>();
}
Вы забыли добавить «services.AddScoped» в стартап-метод «Configureservices».
Эта проблема заключается в том, что вы не зарегистрировали компонент доступа к данным с интерфейсом, написанным для него. Попробуйте использовать следующим образом
services.AddTransient & lt; IMyDataProvider, MyDataAccess & gt; (); `
Если вы используете AutoFac и получаете эту ошибку, вам следует добавить оператор «As», чтобы указать услугу, которую реализует конкретная реализация.
Т.е. ты должен написать:
containerBuilder.RegisterType<DataService>().As<DataService>();
вместо
containerBuilder.RegisterType<DataService>();
Я становился ниже исключения
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()
Потому что я хотел, чтобы register Factory создавал экземпляры класса DbContext Derived IBlogContextFactory и использовал метод создания экземпляра для создания экземпляра контекста блога, чтобы я мог использовать шаблон ниже вместе с зависимостью Injection, а также использовать насмешки для модульного тестирования.
шаблон, который я хотел использовать
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 позаботились.
Я заменил
services.Add (новый ServiceDescriptor (typeof (IMyLogger), typeof (MyLogger))
С
services.AddTransient & lt; IMyLogger, MyLogger & gt; ()
И это сработало для меня.
Я получил эту ошибку, потому что я объявил переменную (выше метода ConfigureServices) типа, который был моим контекстом. Я имел:
CupcakeContext _ctx
Не уверен, о чем я думал. Я знаю, что это законно, если вы передаете параметр методу Configure.
Я получил ошибку: «невозможно разрешить зависимость xxxxxxxx для всех версий ядра .net». Я перепробовал все, что есть в Интернете, и застрял на несколько дней. Единственное решение, которое я придумал, - это добавление файла nuget.config в проект, а затем использование восстановления dotnet, чтобы заставить его работать.
Содержимое файла 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>