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
CodePudding user response:
The problem was solved removing the ApplicationDbContext appDbContext from contructor of repository, and remove the this._context = appDbContext too. but new error Object reference not set to an instance of an object.' in _context appears code after resolving Dependence injection, but with a new nullReference error in _context
CodePudding user response:
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;
}