.NET Core 2.1 Web API控制器通过服务类调用数据库遇404错误排查
让我们一步步排查你遇到的问题,从代码里的明显错误到配置细节:
1. 方法名称不匹配(最直接的触发原因)
看你的控制器代码,你调用的是_dbProvider.ListAllValuesAsync(),但你的DbProvider类里定义的方法是ListItemsAsync——这两个方法名完全不匹配!这要么会导致编译错误,要么运行时抛出找不到方法的异常,最终让接口无法正常响应,表现为404(如果错误处理未配置到位的话)。
修复方案:
把控制器里的调用改成和服务类一致的方法名:
[HttpGet] public async Task<IEnumerable<Dto>> ListAllItemsAsync() { return await _dbProvider.ListItemsAsync(); // 改为服务类中存在的方法名 }
或者修改服务类的方法名与控制器调用保持一致,二选一即可。
2. 缺失DbRepository的依赖注入注册
你的DbProvider依赖DbRepository,但在Startup.ConfigureServices里完全没有注册这个类!当DI容器尝试创建DbProvider实例时,找不到DbRepository的实例,会抛出异常,导致接口无法正常初始化,最终返回404。
修复方案:
在Startup里添加DbRepository的注册(根据业务需求选择生命周期,这里用Transient举例):
services.AddTransient<DbRepository>();
3. Startup中重复注册AddMvc
你的ConfigureServices里先执行了services.AddMvc().SetCompatibilityVersion(...),后面又重复执行了services.AddMvc();——这会覆盖之前的兼容性版本配置,可能导致路由或MVC功能异常。
修复方案:
删除重复的services.AddMvc();,只保留带兼容性配置的那一行:
public void ConfigureServices(IServiceCollection services) { var connString = "database-connectionsting-hardcoded-for-now"; services.AddDbContext<DbContext>(options => options.UseSqlServer(connString)); services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_2); services.AddTransient<DbProvider>(); services.AddTransient<DbRepository>(); // 新增的DbRepository注册 }
4. 确认接口访问路径与路由冲突问题
你的控制器是ValueController,路由是[Route("api/[controller]")],所以正确的接口路径应该是GET https://yourdomain/api/value(注意controller名称会被自动转成小写)。如果你访问的是其他路径(比如/api/values或/api/Value),就会返回404。
另外,同一个控制器里的两个[HttpGet]方法会导致路由匹配冲突——ASP.NET Core无法区分哪个方法对应哪个请求。可以给异步方法指定一个专属路由模板,比如:
[HttpGet("all")] public async Task<IEnumerable<Dto>> ListAllItemsAsync() { return await _dbProvider.ListItemsAsync(); }
这样访问路径就变成/api/value/all,彻底避免和普通Index方法的路由冲突。
5. 检查DbContext的注册是否正确
你当前注册的是DbContext基类,但通常你应该注册自己的自定义DbContext(比如YourAppDbContext : DbContext),否则EF Core无法正确映射你的实体和数据库。如果你的DbRepository依赖的是自定义DbContext,而你注册的是基类,也会导致依赖注入失败。
修复方案:
替换成你的自定义DbContext类型:
services.AddDbContext<YourCustomDbContext>(options => options.UseSqlServer(connString));
把这些点都修复后,重新启动应用,应该就能正常访问你的异步接口了。
内容的提问来源于stack exchange,提问作者Emi

