ASP.NET Core API接口/api/plants/search持续返回404排查求助
ASP.NET Core API /api/plants/search 接口返回404问题排查
问题描述
我正在开发一个ASP.NET Core API,请求/api/plants/search接口时持续返回404错误,尽管控制器和路由配置看似无误。需要识别代码中可能导致该接口出现404错误的配置问题。
已完成的排查步骤
- 本地开发环境部署时一切正常,推测控制器配置无误;
- 确认API已正常运行且可访问数据库;
- 检查了
UseCors、UseAuthentication、UseAuthorization及端点路由的中间件顺序,确保配置正确; - 确认Program.cs中已调用
app.MapControllers();; - 初始配置的
app.MapFallbackToController("Index", "Fallback");已被注释,避免干扰API路由; - 检查IIS配置并禁用了默认文档。
相关代码文件
Program.cs
using API; using API.Data; using API.Extensions; using API.Middleware; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); // 向容器中添加服务。 builder.Services.AddControllers(); builder.Services.AddApplicationServices(builder.Configuration); builder.Services.AddIdentityServices(builder.Configuration); builder.Logging.AddConsole(); var connString = ""; connString = builder.Configuration.GetConnectionString("DefaultConnection"); builder.Services.AddDbContext<DataContext>(opt => { opt.UseSqlServer(connString); }); var app = builder.Build(); // 配置HTTP请求管道。 app.UseMiddleware<ExceptionMiddleware>(); app.UseCors("AllowSpecificOrigin"); app.UseAuthentication(); app.UseAuthorization(); // app.UseDefaultFiles(); // app.UseStaticFiles(); app.MapControllers(); // app.MapFallbackToController("Index", "Fallback"); using var scope = app.Services.CreateScope(); var services = scope.ServiceProvider; try { var context = services.GetRequiredService<DataContext>(); await context.Database.MigrateAsync(); await Seed.SeedAdmin(context); } catch (Exception ex) { var logger = services.GetService<ILogger<Program>>(); logger.LogError(ex, "迁移过程中发生错误"); } app.Run();
appsettings.json(已移除敏感信息)
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Information" } }, "AllowedHosts": "*", "ConnectionStrings": { "DefaultConnection": "CONNECTION STRING" }, "TokenKey": "TOKEN KEY" }
ApplicationServiceExtensions.cs
using API.Data; using API.Interfaces; using API.Services; namespace API.Extensions { public static class ApplicationServiceExtensions { public static IServiceCollection AddApplicationServices(this IServiceCollection services, IConfiguration config) { services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", builder => builder.WithOrigins( "https://localhost:4200", "https://plantguide.ch", "https://www.plantguide.ch", "https://edgarsplantguide.com", "https://www.edgarsplantguide.com" ) .AllowAnyHeader() .AllowAnyMethod()); }); services.AddScoped<ITokenService, TokenService>(); services.AddScoped<IPlantRepository, PlantRepository>(); services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); return services; } } }
BaseApiController.cs
using Microsoft.AspNetCore.Mvc; namespace API.Controllers { [ApiController] [Route("api/[controller]")] public class BaseApiController: ControllerBase { } }
PlantsController.cs
using API.Data; using API.Entities; using API.Interfaces; using AutoMapper; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace API.Controllers; public class PlantsController: BaseApiController { private readonly IPlantRepository _plantRepository; private readonly IMapper _mapper; // 植物控制器构造函数 public PlantsController(IPlantRepository plantRepository, IMapper mapper) { _mapper = mapper; _plantRepository = plantRepository; } [HttpPost("search")] // /api/plants/search public async Task<ActionResult<IEnumerable<Plant>>> SearchPlants([FromBody] PlantSearchFormDto searchDto) { var results = await _plantRepository.GetPlantsBasedOnSearchFormContentAsync(searchDto); return Ok(results); } [HttpGet("{id}")] // /api/plants/1 public async Task<ActionResult<Plant>> GetPlantByIdAsync(int id) { return await _plantRepository.GetPlantByIdAsync(id); } }
可能的问题点及排查建议
- 请求方式不匹配:接口定义为
[HttpPost("search")],如果实际请求使用GET方法,会直接返回404。务必确认请求使用POST发送。 - 模型绑定失败:如果请求体格式与
PlantSearchFormDto不匹配,可能触发400错误,但部分场景下会被误判为404。可以临时将参数改为[FromBody] dynamic searchDto测试,或者提高日志级别(将Microsoft.AspNetCore设为Debug)查看模型绑定详情。 - 路由注册异常:部署环境中可能存在程序集加载问题,导致
PlantsController未被正确注册。可在Program.cs的app.Run()前添加代码输出所有已注册路由,确认/api/plants/search是否存在:var endpointDataSource = app.Services.GetRequiredService<EndpointDataSource>(); foreach (var endpoint in endpointDataSource.Endpoints) { if (endpoint is RouteEndpoint routeEndpoint) { app.Logger.LogInformation("已注册路由: {Route}", routeEndpoint.RoutePattern.RawText); } } - CORS预检请求失败:若请求来源不在
AllowSpecificOrigin列表中,OPTIONS预检请求会失败,前端可能表现为404(实际是CORS错误)。检查请求的Origin是否在允许列表内,或临时改为AllowAnyOrigin()测试。 - IIS路由干扰:即使禁用了默认文档,IIS的URL重写规则可能拦截请求。检查站点的URL重写模块配置,确保没有影响
/api/plants/search的规则。
内容的提问来源于stack exchange,提问作者Philipp
相关产品推荐
相关产品推荐

