I am developing a web application - Blazor WebAssembly hosted on ASP.NET. I am trying to start getting value from database (Entity Framework using). I am using Repository and UnitOfWork patterns in my solution. So, I faced this error:
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: Unable to resolve service for type 'ReportApp.Core.Services.TaskService' while attempting to activate 'ReportApp.Server.Controllers.TaskController'.
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
at lambda_method8(Closure , IServiceProvider , Object[] )
at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.<CreateActivator>b__0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
The structure of my project is as follows:
DbContext
class:
public class ReportAppContext : DbContext
{
public DbSet<TaskEntity> Tasks { get; set; }
public DbSet<ReportEntity> Reports { get; set; }
public DbSet<EmployeeEntity> Employees { get; set; }
public ReportAppContext()
{
}
public ReportAppContext(DbContextOptions<ReportAppContext> options) : base(options)
{
}
}
Repository
interface:
public interface ITaskRepository : IGenericRepository<TaskEntity>
{
}
public interface IGenericRepository<TEntity> where TEntity : class
{
Task<TEntity> GetByIdAsync(Int32 id);
Task InsertAsync(TEntity entity);
Task UpdateAsync(TEntity entity);
Task DeleteAsync(Int32 id);
Task<IEnumerable<TEntity>> GetAllAsync();
Task SaveAsync();
}
public class TaskRepository : ITaskRepository
{
private readonly ReportAppContext _context;
public TaskRepository(ReportAppContext context)
{
_context = context;
}
Then I have UnitOfWork
pattern:
public class UnitOfWork : ReportAppContext, IUnitOfWork
{
private readonly ITaskRepository _taskRepository;
And controller on server:
[Route("api/[controller]")]
[ApiController]
public class TaskController : ControllerBase
{
private readonly TaskService _taskService;
public TaskController(TaskService taskService)
{
_taskService = taskService;
}
[HttpGet("get-all")]
public async Task<ActionResult<List<TaskDto>>> GetAllTasksAsync()
{
var result = await _taskService.GetAllAsync();
return Ok(result);
}
Finally, Startup
class configuration:
public void ConfigureServices(IServiceCollection services)
{
var connection = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<ReportAppContext>(options => options.UseSqlServer(connection));
services.AddCors();
services.AddServerSideBlazor().AddCircuitOptions(options => { options.DetailedErrors = true; });
services.AddControllersWithViews();
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/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();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
I've tried to add this:
services.AddTransient<ITaskRepository, TaskRepository>();
and the same with AddScoped
, but it didn't change anything...
But in your
TaskController
you are injecting TaskService, not TaskRepository. I think you need to register TaskService also (i assume that TaskService consumes TaskRepository. Both can be registered as Scoped).The difference between scoped and transient is that when you have registered service as transient every time when it is resolved return a new instance while scoped will return you same instance during the scope.