REST API返回200响应但生产环境未插入数据问题排查
问题排查与解决方案
按问题出现概率从高到低排查:
- 第一步:确认请求实际路由
不要默认请求打到了你贴的这个接口方法。生产环境大概率存在网关路径重写、旧版本接口残留、路由优先级冲突的问题,导致POST请求被别的空逻辑接口接收、直接返回200,根本没走插入逻辑。
排查方式:在接口入口第一行、JSON校验通过后、SaveChanges调用前、SaveChanges调用后四个节点分别打调试日志,记录请求路径、传入的eventType参数、读取到的请求体内容、SaveChanges返回的受影响行数,先确认代码逻辑有没有实际执行到写入步骤。 - 第二步:验证数据库连接正确性
不要主观判定本地和生产配置完全一致,直接在生产环境运行时打印_dbContext.Database.GetDbConnection().ConnectionString,核对三个点:- 连接的库是否是你查询数据的目标库,排除连错测试库、只读从库的问题
- 连接使用的数据库账号是否对Events表拥有INSERT权限
- 可以临时给Events表加INSERT触发器,记录所有写入操作,排除你查错表、加了默认查询过滤条件没看到新数据的低级错误
- 第三步:排查异常被静默吞的问题
你代码中抛出的HttpResponseException在原生ASP.NET Core框架下不会被自动转换为对应HTTP状态码,如果生产环境配置了全局异常捕获中间件但没处理这个异常类型,很可能把异常兜住后默认返回200响应,实际写入逻辑根本没走完。
排查方式:- 给整个接口逻辑加最外层try-catch,捕获所有异常并打完整错误栈,不要让异常抛到框架层被吞
- 临时去掉接口参数里的CancellationToken,排查生产环境反向代理提前断开请求、触发取消令牌导致SaveChanges被中断但异常没抛出的情况
- 接收SaveChangesAsync的返回值:
int affectRows = await _dbContext.SaveChangesAsync(cancellationToken);,打日志确认返回值是否为1,如果为0说明EF Core没有追踪到你新增的TestEvent实体
- 第四步:修复RequestBody读取的兼容问题
你直接用StreamReader读取RequestBody的写法存在环境兼容问题:生产环境如果启用了请求日志、HTTPS重定向、模型验证等内置/自定义中间件,这些中间件会提前读取RequestBody,默认情况下请求流读完不会自动重置位置,你后续读取会拿到空内容甚至触发流已释放的异常。
修复后的参考代码:[Route( "api/event/{eventType}/new" )] [HttpPost] public async Task AddEvent( string eventType, CancellationToken cancellationToken ) { if ( string.IsNullOrWhiteSpace( eventType ) ) throw new HttpResponseException( 400, "Route wrong: no valid eventType given" ); // 启用请求缓冲,允许多次读取 Request.EnableBuffering(); using var reader = new StreamReader( HttpContext.Request.Body, Encoding.UTF8, leaveOpen:true ); var postedEvent = await reader.ReadToEndAsync(); // 重置流位置,避免影响后续中间件 HttpContext.Request.Body.Position = 0; try { JsonConvert.DeserializeObject( postedEvent ); } catch ( Exception ex ) { throw new HttpResponseException( 400, "Payload is not valid JSON" ); } var testEvent= new TestEvent{ EventType = eventType, EventData = postedEvent }; _dbContext.Events.Add( testEvent); await _dbContext.SaveChangesAsync( cancellationToken ); } - 额外排查点:核对生产环境Web服务器、网关的CORS配置、请求拦截规则,确认你传
Content-Type: text/plain的请求没有被策略直接拦截返回200,没有触发请求体大小限制导致请求被截断。
内容的提问来源于stack exchange,提问作者Ocelot
相关产品推荐
相关产品推荐

