ASP.NET Core 6 Clean Architecture Web API服务解析失败问题求助
问题描述
基于ASP.NET Core 6构建Clean Architecture风格的Web API,测试CRUD的Get方法时触发System.InvalidOperationException: Unable to resolve service错误。各层结构如下:
- 持久化层:包含
ISPRepository接口、SPRepository实现类及SPContext - 应用层:实现
IGetSPService接口与GetSPService实现类 - API层:
SPController依赖IGetSPService
持久化层代码
ISPRepository接口
using Domain.Entities; using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; namespace Domain.Interfaces.IRepositories { public interface ISPRepository { Task<List<SP>> GetByIdsAsync(int ids); Task<List<SP>> GetAllAsync(); } }
SPRepository实现类
using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Domain.Entities; using Domain.Interfaces.IRepositories; using Persistence.DBContext; namespace Persistence.Repositories { public class SPRepository: ISPRepository { private readonly SPContext _context; // 根据ID获取SP public async Task<List<SP>> GetByIdsAsync(int ids) { return await this._context .SPs .Where(x => x.SPId==ids).ToListAsync(); } // 获取所有SP public async Task<List<SP>> GetAllAsync() { return await this._context .SPs .ToListAsync(); } } }
应用层代码
IGetSPService接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SP.Domain.Entities; namespace SP.Application.SP.Queries.Iservices { public interface IGetSPService { Task<List<SP>> GetSPByIdAsync(int SPId); Task<List<SP>> GetAllAsync(); } }
GetSPService实现类
using SP.Domain.Interfaces.IRepositories; using SP.Domain.Entities; using SP.Application.SP.Queries.Iservices; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SP.Application.SP.Queries.Services { public class GetSPService: IGetSPService { private readonly ISPRepository _SPRepository; public GetSPService(ISPRepository SPRepository) { _SPRepository = SPRepository; } public async Task<List<SP>> GetSPByIdAsync(int SPId) { return await _SPRepository.GetByIdsAsync(SPId); } public async Task<List<SP>> GetAllAsync() { return await _SPRepository.GetAllAsync(); } } }
API层代码
SPController
using Microsoft.AspNetCore.Mvc; using SP.Application.SP.Queries.Iservices; using SP.Domain.Entities; using System.Xml; namespace SP.Api.Server.Controllers { [ApiController] [Route("api/[controller]")] public class SPController : ControllerBase { private readonly IGetSPService _service; public SPController(IGetSPService service) { _service = service; } [HttpGet("{id}")] public async Task<ActionResult<List<SP>>> GetSPById(int id) { var entity = await _service.GetSPByIdAsync(id); if (entity == null) { return NotFound(); } return entity; } } }
原Program.cs代码
using Microsoft.EntityFrameworkCore; using SP.Persistence.DBContext; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddHttpContextAccessor();*/ var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); // 解决localhost无法访问问题 app.UsePathBase("/SP.Api.Server"); app.UseAuthorization(); app.MapControllers(); app.Run();
问题原因与解决方法
错误核心是ASP.NET Core依赖注入容器未注册所需的服务接口与实现类,同时SPContext也未完成注册。需在Program.cs中补充以下注册逻辑:
修改后的Program.cs代码
using Microsoft.EntityFrameworkCore; using SP.Persistence.DBContext; using Domain.Interfaces.IRepositories; using Persistence.Repositories; using SP.Application.SP.Queries.Iservices; using SP.Application.SP.Queries.Services; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // 1. 注册SPContext,配置数据库连接(示例为SQL Server,可根据实际替换) builder.Services.AddDbContext<SPContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 2. 注册仓储:绑定接口与实现类 builder.Services.AddScoped<ISPRepository, SPRepository>(); // 3. 注册应用服务:绑定接口与实现类 builder.Services.AddScoped<IGetSPService, GetSPService>(); builder.Services.AddHttpContextAccessor(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UsePathBase("/SP.Api.Server"); app.UseAuthorization(); app.MapControllers(); app.Run();
关键说明
- SPContext注册:需在
appsettings.json中配置对应连接字符串DefaultConnection,示例:{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=SPDB;Trusted_Connection=True;MultipleActiveResultSets=true" } } - 仓储与服务注册:使用
AddScoped(每个请求生命周期创建一个实例)完成接口与实现类的绑定,符合Clean Architecture的依赖倒置原则,容器会在需要时自动解析对应实现类。
内容的提问来源于stack exchange,提问作者Mira
相关产品推荐
相关产品推荐

