InvalidOperationException: No database provider has been configured for this DbContext. - c#

build a web api using entityframeworkcore 2.03 .net core
keep getting the following error tried everything i can think of to get past it not sure what the issue is has anyone else had this iasue ?
InvalidOperationException: No database provider has been configured
for this DbContext. A provider can be configured by overriding the
DbContext.OnConfiguring method or by using AddDbContext on the
application service provider. If AddDbContext is used, then also
ensure that your DbContext type accepts a DbContextOptions
object in its constructor and passes it to the base constructor for
DbContext
startup.cs
using churchy.Repository;
using churchy.Service;
using churchy.Service.Abstractions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace churchy
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Database connection
services.AddDbContext<ChurchContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ChurchConnection")));
// Repositories
services.AddScoped<IRepository, Repository.Repository>();
services.AddScoped<IRepositoryFactory, RepositoryFactory>();
// Services
services.AddScoped<IChurchService, ChurchService>();
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
churchcontext.cs
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.EntityFrameworkCore;
using churchy.Model;
namespace churchy.Repository
{
public class ChurchContext: DbContext
{
public ChurchContext()
{
}
public ChurchContext(DbContextOptions<ChurchContext> options) : base(options)
{
}
public DbSet<Church> Churches { get; set; }
public DbSet<Location> Locations { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Church>().ToTable("Church");
}
}
}
Repository.cs
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;
namespace churchy.Repository
{
public class Repository : IRepository
{
private readonly ChurchContext _context;
public Repository()
{
_context = new ChurchContext();
}
public IQueryable<T> GetAll<T>() where T : class
{
return _context.Set<T>();
}
public Task Create<T>(T entity) where T : class
{
throw new System.NotImplementedException();
}
public Task Delete<T>(int id) where T : class
{
throw new System.NotImplementedException();
}
public Task Update<T>(int id, T entity) where T : class
{
throw new System.NotImplementedException();
}
public void Dispose()
{
_context?.Dispose();
}
}
}
IRepository.cs
using System;
using System.Linq;
using System.Threading.Tasks;
namespace churchy.Repository
{
public interface IRepository : IDisposable
{
IQueryable<T> GetAll<T>() where T : class;
Task Create<T>(T entity) where T :class;
Task Update<T>(int id, T entity) where T : class;
Task Delete<T>(int id) where T : class;
}
}
ChurchController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using churchy.Service.Abstractions;
namespace churchy.Controllers
{
[Route("api/church")]
public class ChurchController : Controller
{
private readonly IChurchService _churchService;
public ChurchController(IChurchService churchService)
{
_churchService = churchService;
}
// GET: api/<controller>
[HttpGet]
public IActionResult GetAllAsync()
{
var response = _churchService.getChurches();
return Ok(response);
}
// GET api/<controller>/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value3";
}
// POST api/<controller>
[HttpPost]
public void Post([FromBody]string value)
{
}
// PUT api/<controller>/5
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/<controller>/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}

Here is your most fundamental problem:
public Repository()
{
_context = new ChurchContext();
}
That's the opposite of Dependency Injection. That context you are manually creating has not been configured.
Quick answer:
public Repository(ChurchContext context)
{
_context = context;
}
Furthermore:
You should get familiar with Dependency Injection in ASP.NET Core: Dependency Injection in ASP.NET Core.
You may want to read this answer of mine for some viewpoints regarding UoW and Repository patterns in ASP.NET Core.

Related

Error while creating Dependency Injection on ASP.NET Core 6.0 MVC

I am doing chat app, and it was working before I start to create 3 layers layout (controller, service and repository) with dependency injection.
This was the format before I started to change to 3 layer layout, data access in controller:
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using ChatApplication.Data;
using MyWebChatApp.Models;
using Microsoft.AspNetCore.Authorization;
namespace ChatApplication.Controllers
{
[Authorize]
public class MessageController : Controller
{
private readonly ApplicationDbContext _context;
public MessageController(ApplicationDbContext context)
{
_context = context;
}
// GET: Message
public async Task<IActionResult> Index()
{
return View(await _context.Message.ToListAsync());
}
This is the error I am getting, I tried to put in layers but I am getting that error:
An error occurred while starting the application.
AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Repositories.Contracts.IRepository`1[Repositories.Models.Message] Lifetime: Singleton ImplementationType: Repositories.Repositories.MessageRepository': Unable to resolve service for type 'Repositories.Data.ApplicationDbContext' while attempting to activate 'Repositories.Repositories.MessageRepository'.) (Error while validating the service descriptor 'ServiceType: Services.Services.interfaces.IMessageService Lifetime: Singleton ImplementationType: Services.Services.MessageService': Unable to resolve service for type 'Repositories.Data.ApplicationDbContext' while attempting to activate 'Repositories.Repositories.MessageRepository'.)
Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection serviceDescriptors, ServiceProviderOptions options)
InvalidOperationException: Error while validating the service descriptor 'ServiceType: Repositories.Contracts.IRepository`1[Repositories.Models.Message] Lifetime: Singleton ImplementationType: Repositories.Repositories.MessageRepository': Unable to resolve service for type 'Repositories.Data.ApplicationDbContext' while attempting to activate 'Repositories.Repositories.MessageRepository'.
Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
This is the code I made trying to put in 3 layers:
Program.cs
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using ChatApplication.Data;
using Repositories.Contracts;
using Repositories.Models;
using Repositories.Repositories;
using Services.Services.interfaces;
using Services.Services;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
builder.Services.AddSingleton<IRepository<Message>, MessageRepository>();
builder.Services.AddSingleton<IMessageService, MessageService>();
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
MessageController
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using ChatApplication.Data;
using Microsoft.AspNetCore.Authorization;
using Services.Services.interfaces;
using Repositories.Models;
namespace ChatApplication.Controllers
{
[Authorize]
public class MessageController : Controller
{
private readonly IMessageService _messageService;
public MessageController(IMessageService messageService)
{
this._messageService = messageService;
}
// GET: Message
public async Task<IActionResult> Index()
{
return View(await _messageService.GetChatMessages());
}
}
}
MessageService
using Repositories.Contracts;
using Repositories.Models;
using Services.Services.interfaces;
namespace Services.Services
{
public class MessageService : IMessageService
{
public readonly IRepository<Message> messageRepository;
public MessageService(IRepository<Message> repository)
{
messageRepository = repository;
}
public async Task<IEnumerable<Message>> GetChatMessages()
{
try
{
return await messageRepository.GetAll();
}
catch (Exception ex)
{
throw;
}
}
}
}
IMessageService
using Repositories.Models;
namespace Services.Services.interfaces
{
public interface IMessageService
{
Task<IEnumerable<Message>> GetChatMessages();
Task SendMessage(Message message);
Task<Message> GetMessageById(int? id);
void EditMessage(Message message);
void DeleteMessage(int id);
}
}
MessageRepository
using Microsoft.EntityFrameworkCore;
using Repositories.Contracts;
using Repositories.Data;
using Repositories.Models;
namespace Repositories.Repositories
{
public class MessageRepository : IRepository<Message>
{
private readonly ApplicationDbContext _context;
public MessageRepository(ApplicationDbContext context)
{
_context = context;
}
public async Task<IEnumerable<Message>> GetAll()
{
return await _context.Message.ToListAsync();
}
}
}
IRepository
using Repositories.Models;
namespace Repositories.Contracts
{
public interface IRepository <T>
{
Task Create(T obj);
Task<IEnumerable<T>> GetAll();
void Update(T entity);
void Delete(int id);
Task<T> GetById(int? id);
}
}
I don't know what I have to do to my services and repositories works
the final solution of the problem was add
builder.Services.AddScoped<IRepository<Message>, MessageRepository>();
builder.Services.AddScoped<IMessageService, MessageService>();
builder.Services.AddScoped<ApplicationDbContext, ApplicationDbContext>();
and complete contructor on repository
public class MessageRepository : IRepository<Message>
{
private readonly ApplicationDbContext _context;
public MessageRepository(ApplicationDbContext c)
{
this._context = c;
}

ApplicationDBContext declares a parameterless constructor

Trying to learn EF Core, have just finished a course online and I am trying to get an integer added to a DB table. .Net 5.0.
I am getting an error when I build the application:
'AddDbContext' was called with configuration, but the context type 'ApplicationDbContext' only declares a parameterless constructor. This means that the configuration passed to 'AddDbContext' will never be used. If configuration is passed to 'AddDbContext', then 'ApplicationDbContext' should declare a constructor that accepts a DbContextOptions and must pass it to the base constructor for DbContext.
Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CheckContextConstructors()
I understand the problem is between ApplicationDBContext.cs and Startup.cs, one has parameters and one is parameterless, but I don't know how to fix it. Other answers online seem to be along the lines of "This is obvious, just fix it" which is not very helpful.
ApplicationDBContext
If I un-comment the empty ApplicationDbContext functions I no longer get the error, but when I run the program nothing is added to my DB.
using System;
using System.Collections.Generic;
using System.Text;
using MyApp.Areas.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace MyApp.Data
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<RGWAction> RGWActions { get; set; }
DBConnectionStringFactory GetDBConnectionString = new DBConnectionStringFactory();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string ConnectionString = GetDBConnectionString.DBConnectionString();
optionsBuilder.UseSqlServer(ConnectionString).LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Command.Name },LogLevel.Information)
.EnableSensitiveDataLogging(); //add to be able to see parameters in your log
}
/*
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public ApplicationDbContext()
{
}
*/
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services) method
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
RGWAction.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace MyApp.Areas.Identity
{
public class RGWAction
{
public int Id { get; set; }
public string Email { get; set; }
public int Total { get; set; }
public int ReduceMeat { get; set; }
}
}
Program.cs
Just trying to add an integer to the DB on startup right now, to get it working as a learning exercise. My next step will be to trigger it from a UI button.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MyApp.Data;
using MyApp.Areas.Identity;
namespace MyApp
{
public class Program
{
private static ApplicationDbContext _context = new ApplicationDbContext();
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
InsertNewInteger();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
private static void InsertNewInteger()
{
_context.RGWActions.Add(new RGWAction { ReduceMeat = 1 });
_context.SaveChanges();
}
}
}
DB Table:
Advice would be much appreciated.
You need an ApplicationDbContext constructor with a DbContextOptions parameter to insert option dependencies.
You need a default constructor without parameters because you call it explicitly in the _context field initializer. Try to omit this initialization, it is unnecessary if DI works well.
Your controller:
public class YourController : Controller
{
[HttpPost] // because data is updated
public async Task<ActionResult> NewIntAction(
[FromServices]
INewIntService newIntService)
{
await newIntService.InsertNewInteger();
....
return View(); // You will need a view NewIntAction in the folder Views/Your
}
}
INewIntService interface :
public interface INewIntService
{
Task InsertNewInteger();
}
NewIntService class:
public sealed class NewIntService : INewIntService
{
public NewIntService(ApplicationDbContext context)
{
_context = context;
}
ApplicationDbContext _context;
public async Task InsertNewInteger()
{
_context.RGWActions.Add(new RGWAction { ReduceMeat = 1 });
await _context.SaveChangesAsync();
}
}
Startup.cs:
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddTransient<INewIntService, NewIntService>();
Main program:
namespace MyApp
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
InsertNewInteger();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
I need define no constructor of ApplicationDbContext because the instance of ApplicationDbContext is created by the infrastructure and injected as a dependency into the NewIntService constructor in its context parameter.
Ahhhh, finally! :)
ApplicationDBContext needs all three methods. Does anyone know why?
OnConfiguring(DbContextOptionsBuilder optionsBuilder)
ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
ApplicationDbContext()
Also Program.cs was the wrong place for my InsertNewInteger() method. It needed to be in the controller for the page load, in this case index.cs controller.

How to do dependency injection on a noncontroller in asp.net core?

I'm trying to create a context for my redis database without using Entity Framework. My connection depends on a ConnectionMultiplexer class, so for unit testing I'm trying to use dependency injection. I'm not sure how to create the using statement for my context without the ConnectionMultiplexer parameter.
Am I doing dependency injection wrong? How can I restructure so I can use the "using" context correctly and have it resolve the dependency for me?
GameSession.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using StackExchange.Redis;
namespace Bored.GameService.GameSession
{
public class GameSessionContext : IGameSession, IDisposable
{
private IDatabase conn;
private readonly IConnectionMultiplexer _muxer;
public GameSessionContext(IConnectionMultiplexer muxer)
{
_muxer = muxer;
string connectionString = Startup.Configuration.GetConnectionString("redis");
_muxer = ConnectionMultiplexer.Connect(connectionString);
//conn = muxer.GetDatabase();
//conn.StringSet("foo", "bar");
//var value = conn.StringGet("foo");
//Console.WriteLine(value);
}
public void GetGameState()
{
throw new NotImplementedException();
}
public void AddGameState()
{
throw new NotImplementedException();
}
public void Dispose()
{
_muxer.Dispose();
}
}
}
Here is where I'm registering the dependency in my startup.cs
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConnectionMultiplexer, ConnectionMultiplexer>();
services.AddSignalR();
services.AddCors(options =>
{
options.AddPolicy("ClientPermission", policy =>
{
policy.AllowAnyHeader()
.AllowAnyMethod()
.WithOrigins("http://localhost:3000")
.AllowCredentials();
});
});
}
Here is how I'm using it in my GameServiceAPI class:
using Bored.GameService.Clients;
using Bored.GameService.GameSession;
using Bored.GameService.Models;
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
namespace Bored.GameService.GameServiceAPI
{
public class GameServiceHub : Hub<IGameClient>
{
public Task SendMessage(GameMessage message)
{
// Throws an error because GameSessionContext has no IConnectionMultiplexer parameter passed in.
using (var context = new GameSessionContext())
{
// var gameState = context.GetGameState(context);
// context.AddGameState(gameState);
// Clients.All.ReceiveMessage(gameState);
}
return Clients.All.ReceiveMessage(message);
}
}
}
Thanks to #DavidBrowne's suggestion for registering both the GameServiceHub and GameSessionContext with DI.
Here's the code I used to get this to work:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect(Configuration.GetConnectionString("redis")));
services.AddScoped<IGameSessionContext, GameSessionContext>();
services.AddSignalR();
services.AddCors(options =>
{
options.AddPolicy("ClientPermission", policy =>
{
policy.AllowAnyHeader()
.AllowAnyMethod()
.WithOrigins("http://localhost:3000")
.AllowCredentials();
});
});
GameSessionContext.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using StackExchange.Redis;
namespace Bored.GameService.GameSession
{
public class GameSessionContext : IGameSessionContext
{
private IDatabase conn;
private readonly IConnectionMultiplexer _muxer;
public GameSessionContext(IConnectionMultiplexer muxer)
{
_muxer = muxer;
}
public string GetGameState()
{
conn = _muxer.GetDatabase();
conn.StringSet("foo", "Here's game state");
return conn.StringGet("foo");
}
public void AddGameState()
{
throw new NotImplementedException();
}
}
}
GameServiceHub.cs
using Bored.GameService.Clients;
using Bored.GameService.GameSession;
using Bored.GameService.Models;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Threading.Tasks;
namespace Bored.GameService.GameServiceAPI
{
public class GameServiceHub : Hub<IGameClient>
{
private IGameSessionContext _context;
public GameServiceHub(IGameSessionContext context)
{
_context = context;
}
public Task SendMessage(GameMessage message)
{
var state = _context.GetGameState();
Console.WriteLine(state);
// var gameState = context.GetGameState(context);
// context.AddGameState(gameState);
return Clients.All.ReceiveMessage(message);
}
}
}

ASP.NET Core Web API InvalidOperationException: Unable to resolve service [duplicate]

This question already has answers here:
Dependency Injection error: Unable to resolve service for type while attempting to activate, while class is registered
(29 answers)
Closed 2 years ago.
i'm trying to build a simple api as a test to a future api for a project. But i keep having this error
InvalidOperationException: Unable to resolve service for type
'AspnetCore_WebApi.Models.TarefaContext' while attempting to activate
'AspnetCore_WebApi.Models.TarefaRepositorio'.
Here is TarefaContext.cs
using Microsoft.EntityFrameworkCore;
namespace AspnetCore_WebApi.Models
{
public class TarefaContext : DbContext
{
public TarefaContext(DbContextOptions<TarefaContext> options)
: base(options)
{ }
public DbSet<TarefaItem> TarefaItens { get; set; }
}
}
TarefaRepositorio.cs
using System.Collections.Generic;
using System.Linq;
namespace AspnetCore_WebApi.Models
{
public class TarefaRepositorio : ITarefaRepositorio
{
private readonly TarefaContext _context;
public TarefaRepositorio(TarefaContext context)
{
_context = context;
Add(new TarefaItem { Nome = "Item1" });
}
public IEnumerable<TarefaItem> GetAll()
{
return _context.TarefaItens.ToList();
}
public void Add(TarefaItem item)
{
_context.TarefaItens.Add(item);
_context.SaveChanges();
}
public TarefaItem Find(long key)
{
return _context.TarefaItens.FirstOrDefault(t => t.Chave == key);
}
public void Remove(long key)
{
var entity = _context.TarefaItens.First(t => t.Chave == key);
_context.TarefaItens.Remove(entity);
_context.SaveChanges();
}
public void Update(TarefaItem item)
{
_context.TarefaItens.Update(item);
_context.SaveChanges();
}
}
}
TarefaController.cs
using System.Collections.Generic;
using AspnetCore_WebApi.Models;
using Microsoft.AspNetCore.Mvc;
namespace AspnetCore_WebApi.Controllers
{
[Route("api/[controller]")]
public class TarefaController : Controller
{
private readonly ITarefaRepositorio _tarefaRepositorio;
public TarefaController(ITarefaRepositorio tarefaRepositorio)
{
_tarefaRepositorio = tarefaRepositorio;
}
[HttpGet]
public IEnumerable<TarefaItem> GetAll()
{
return _tarefaRepositorio.GetAll();
}
[HttpGet("{id}", Name = "GetTarefa")]
public IActionResult GetById(long id)
{
var item = _tarefaRepositorio.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
[HttpPost]
public IActionResult Create([FromBody] TarefaItem item)
{
if (item == null)
{
return BadRequest();
}
_tarefaRepositorio.Add(item);
return CreatedAtRoute("GetTarefa", new { id = item.Chave }, item);
}
}
}
ITarefaRepositorio.cs
using System.Collections.Generic;
namespace AspnetCore_WebApi.Models
{
public interface ITarefaRepositorio
{
void Add(TarefaItem item);
IEnumerable<TarefaItem> GetAll();
TarefaItem Find(long key);
void Remove(long key);
void Update(TarefaItem item);
}
}
Error message describes that dependency injection cannot resolve your TarefaContext class. You should register your db context in your startup ConfigureServices method using services.AddDbContext method.
For more information see Microsoft documentation: https://learn.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext
As Scott and Artis said in https://stackoverflow.com/a/62643033/12934203 I haven't added my Context Class to the startup.cs file. I had some trouble with the article mentioned by Artis because I'm using EF Core InMemory so I jus had to add
services.AddDbContext<TarefaContext>(options => options.UseInMemoryDatabase());
to the ConfigureServices at Startup.cs instead
services.AddDbContext<TarefaContext>(options => options.UseSqlite("Data Source=someDB.db"));
Thank y'all for helping

Dependency Injection fails with MVC5 and Ninject

I'm trying to inject a couple of classes in a controller, but I'm failing.
This is what I've done:
Added Ninject.Web.WebApi.WebHost and WebActivatorEx NuGet packages
Created the following class under App_Start:
NinjectWebCommon.cs
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.Common.WebHost;
using MyProject;
using MyProject.Models;
using MyProject.Classes;
using System;
using System.Web;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(NinjectWebCommon), "Stop")]
namespace MyProject
{
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IMyContext>().ToSelf().InRequestScope();
kernel.Bind<IErp>().ToSelf().InRequestScope();
}
}
}
Created my classes:
MyContext.cs:
using MyProject.Models;
using System;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Threading.Tasks;
namespace MyProject.Models
{
public interface IMyContext : IDisposable
{
DbSet<Operator> Operators { get; set; }
Task<int> SaveChangesAsync();
}
public class MyContext : DbContext, IMyContext
{
public MyContext () : base("MyContext ") { }
public DbSet<Operator> Operators { get; set; }
public async override Task<int> SaveChangesAsync()
{
return await SaveChangesAsync(CancellationToken.None);
}
}
}
Erp.cs
public interface IErp
{
Task ImportListAsync();
}
public class Erp : IErp
{
private readonly IMyContext _context;
public Erp(IMyContext context)
{
_context = context;
}
public async Task ImportListAsync()
{
// do something
}
}
Created a Controller
using MyProject.Classes;
using MyProject.Models;
using System.Data.Entity;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace MyProject.Controllers
{
public class OperatorsController : Controller
{
private readonly IMyContext _context;
private readonly IErp _erp;
public OperatorsController(IMyContext context, Erp Ierp)
{
_context = context;
_erp = erp;
}
// GET: Operators
public async Task<ActionResult> Index()
{
return View(await _context.Operators.ToListAsync());
}
// GET: Operators/Import
public async Task<ActionResult> Import()
{
await _erp.ImportListAsync();
return View("Index", await _context.Operators.ToListAsync());
}
}
}
But when I run the application I still get the infamous error about the missing of parameterless constructor. This says to me that DI is not working.
I believe your registration calls in RegisterServices are wrong - you cannot bind an interface .ToSelf() - you need to bind the interface to the concrete class that implements it - something like this:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IMyContext>().To<MyContext>().InRequestScope();
kernel.Bind<IErp>().To<Erp>().InRequestScope();
}
With this, you tell the DI container to instantiate an MyContext class whenever in your code you're expecting an IMyContext dependency

Categories

Resources