System.InvalidOperationException: 无法解析服务类型 - 依赖注入
System.InvalidOperationException: Unable to resolve service for type - Dependency Injection
我正在开发 Web 应用程序 - 托管在 ASP.NET 上的 Blazor WebAssembly。我正在尝试开始从数据库中获取价值(Entity Framework 使用)。我在我的解决方案中使用 Repository 和 UnitOfWork 模式。
所以,我遇到了这个错误:
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)
我的项目结构如下:
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
接口:
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;
}
然后我有 UnitOfWork
模式:
public class UnitOfWork : ReportAppContext, IUnitOfWork
{
private readonly ITaskRepository _taskRepository;
服务器上的控制器:
[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);
}
最后,Startup
class配置:
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");
});
}
我试过添加这个:
services.AddTransient<ITaskRepository, TaskRepository>();
与AddScoped
相同,但没有任何改变...
但是在您的 TaskController
中,您注入的是 TaskService,而不是 TaskRepository。我认为您还需要注册 TaskService(我假设 TaskService 使用 TaskRepository。两者都可以注册为 Scoped)。
services.AddTransient<ITaskRepository, TaskRepository>(); OR
services.AddScoped<ITaskRepository, TaskRepository>();
services.AddTransient<TaskService>(); OR
services.AddScoped<TaskService>();
作用域和瞬态之间的区别在于,当您将服务注册为瞬态时,每次解析时 return 一个新实例,而作用域将 return 您在作用域中的同一实例。
错误告诉您 TaskService 未注册,但您的 Controller 需要它作为注入服务。
在 ConfigureServices 中,尝试这样的操作:
services.AddScoped<TaskService>(sp => {
// Build your Context Options
DbContextOptionsBuilder<ReportAppContext> optsBuilder = new DbContextOptionsBuilder<ReportAppContext>();
optsBuilder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
// Build your context (using the options from the builder)
ReportAppContext ctx = new ReportAppContext(optsBuilder.options);
// Build your unit of work (and pass in the context)
UnitOfWork uow = new UnitOfWork(ctx);
// Build your service (and pass in the unit of work)
TaskService svc = new TaskService(uow)
// Return your Svc
return svc;
});
然后,您的控制器将收到一个完全配置的 TaskService,可供使用。
如果你愿意,你可以将每个项目依次放入DI容器中,但是UOW,Repository和Context不需要在TaskService之外访问,所以有点浪费时间。
只需要像上面那样创建配置好的TaskService即可,DI容器需要注入的就这些了。
我正在开发 Web 应用程序 - 托管在 ASP.NET 上的 Blazor WebAssembly。我正在尝试开始从数据库中获取价值(Entity Framework 使用)。我在我的解决方案中使用 Repository 和 UnitOfWork 模式。 所以,我遇到了这个错误:
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)
我的项目结构如下:
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
接口:
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;
}
然后我有 UnitOfWork
模式:
public class UnitOfWork : ReportAppContext, IUnitOfWork
{
private readonly ITaskRepository _taskRepository;
服务器上的控制器:
[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);
}
最后,Startup
class配置:
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");
});
}
我试过添加这个:
services.AddTransient<ITaskRepository, TaskRepository>();
与AddScoped
相同,但没有任何改变...
但是在您的 TaskController
中,您注入的是 TaskService,而不是 TaskRepository。我认为您还需要注册 TaskService(我假设 TaskService 使用 TaskRepository。两者都可以注册为 Scoped)。
services.AddTransient<ITaskRepository, TaskRepository>(); OR
services.AddScoped<ITaskRepository, TaskRepository>();
services.AddTransient<TaskService>(); OR
services.AddScoped<TaskService>();
作用域和瞬态之间的区别在于,当您将服务注册为瞬态时,每次解析时 return 一个新实例,而作用域将 return 您在作用域中的同一实例。
错误告诉您 TaskService 未注册,但您的 Controller 需要它作为注入服务。
在 ConfigureServices 中,尝试这样的操作:
services.AddScoped<TaskService>(sp => {
// Build your Context Options
DbContextOptionsBuilder<ReportAppContext> optsBuilder = new DbContextOptionsBuilder<ReportAppContext>();
optsBuilder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
// Build your context (using the options from the builder)
ReportAppContext ctx = new ReportAppContext(optsBuilder.options);
// Build your unit of work (and pass in the context)
UnitOfWork uow = new UnitOfWork(ctx);
// Build your service (and pass in the unit of work)
TaskService svc = new TaskService(uow)
// Return your Svc
return svc;
});
然后,您的控制器将收到一个完全配置的 TaskService,可供使用。
如果你愿意,你可以将每个项目依次放入DI容器中,但是UOW,Repository和Context不需要在TaskService之外访问,所以有点浪费时间。
只需要像上面那样创建配置好的TaskService即可,DI容器需要注入的就这些了。