C# Web API 2.0 POST请求始终Pending,返回204则正常求排查
我帮你排查了下,这个问题的核心原因出在EF实体的序列化环节,具体来说是循环引用或者延迟加载导致序列化卡住,使得响应一直无法生成完成,所以请求一直处于Pending状态;而返回204 No Content时没有响应体,不需要序列化,自然就能正常结束请求。
具体原因拆解:
看你的代码,POST接口里return Ok(newItem)返回的是TeamnewsView这个EF实体对象(来自DWP.Data.Model),而ASP.NET Web API默认用JSON.NET序列化响应内容。如果这个实体有导航属性(比如关联了NewsItem之类的其他实体),或者EF的延迟加载是开启状态的话:
- 序列化器在处理实体时,会自动尝试访问所有可访问的属性,包括导航属性
- 如果导航属性又反向关联回
TeamnewsView,就会形成循环引用(比如TeamnewsView -> NewsItem -> TeamnewsView -> ...),JSON.NET会陷入无限循环,一直无法完成序列化 - 即使没有循环引用,延迟加载也会触发EF去数据库加载关联数据,这个过程如果卡住或者耗时过长,也会导致响应迟迟无法返回
而返回204状态码时,API不需要返回任何响应体,跳过了序列化步骤,所以请求能正常走完整个流程。
解决方案(按推荐程度排序):
1. 改用ViewModel返回(最推荐,和你的Get方法保持一致)
就像你在Get接口里做的那样,不要直接返回EF实体,而是映射到TeamnewsViewsViewModel后再返回。这样既能避免序列化问题,也能控制返回给前端的字段,符合前后端分离的最佳实践。
修改你的Post接口代码:
[HttpPost] [ActionName("Increment")] public IHttpActionResult Post(string teamnewsItemId) { if (teamnewsItemId == "") { return BadRequest("The newsitem Id is invalid"); } var teamNewsItem = _teamnewsViewsService.GetTeamnewsView(teamnewsItemId); if (teamNewsItem == null) { return NotFound(); } var newItem = _teamnewsViewsService.IncrementViewCount(teamNewsItem); // 把EF实体映射到ViewModel var viewModel = new TeamnewsViewsViewModel { Id = newItem.Id, TenantId = newItem.TenantId, NewsItemId = newItem.NewsItemId, ViewCount = newItem.ViewCount }; return Ok(viewModel); }
2. 关闭EF的延迟加载和代理创建
如果你暂时不想改用ViewModel,可以在你的DbContext构造函数里关闭延迟加载和动态代理,这样实体不会包含导航属性的代理对象,序列化时就不会触发额外的数据库查询或循环引用:
public class YourDbContext : DbContext { public YourDbContext() { Configuration.LazyLoadingEnabled = false; Configuration.ProxyCreationEnabled = false; } // ...其他DbSet和配置 }
3. 配置JSON.NET忽略循环引用
在WebApiConfig.cs里配置JSON.NET忽略循环引用,这样序列化器遇到循环引用时会跳过,不会无限循环:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // ...其他路由配置 config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; } }
不过这种方法可能会导致部分关联属性被意外忽略,不如ViewModel的方式可控。
验证:
修改后再测试POST接口,应该就能正常返回响应,不会再出现Pending的情况了。
内容的提问来源于stack exchange,提问作者Rodney Wormsbecher

