.NET Core 6 Web API存在数据时返回404,动态属性序列化异常排查
问题分析与解决方案
问题背景
基于MongoDB和.NET Core 6开发的API接口出现异常:当数据库存在匹配数据时返回404错误,无匹配数据时可正常返回提示。经排查,问题根源在于JSON序列化环节,具体出在实体类的dynamic类型属性UserDocument的序列化过程中,且序列化出错时无明显错误日志或异常跟踪信息。
控制器代码
[HttpPost("FilterUsers")] public async Task<IActionResult> gUsersFiltered([FromBody] gFilterRequest gr) { if (gr.Key.Equals("Email")) { var users = await Task.Run(() => _gRepo .FilterBy(x => x.Email.Equals(gr.Value)).AsQueryable()); return Ok(users); } }
实体类相关属性
[BsonElement("UserDocument")] public dynamic UserDocument { get; set; };
问题原因
当数据库存在数据时,API需要序列化包含UserDocument属性的实体对象:
- 由于使用MongoDB驱动,
dynamic类型的UserDocument实际会被反序列化为BsonDocument类型 - .NET Core默认的
System.Text.Json序列化器无法直接处理BsonDocument,序列化时会抛出未捕获的异常 - 该异常未被正确捕获处理,导致ASP.NET Core请求流程中断,最终返回不符合预期的404错误(通常是异常处理中间件配置问题导致错误码显示异常)
解决方案
方案1:替换dynamic为具体实体类
如果UserDocument有固定数据结构,直接定义对应的实体类替代dynamic,让序列化器能正常处理:
// 定义UserDocument实体类 public class UserDocument { public string DocumentName { get; set; } public DateTime CreateTime { get; set; } // 补充其他实际属性 } // 修改实体类属性 [BsonElement("UserDocument")] public UserDocument UserDocument { get; set; };
方案2:改用Newtonsoft.Json(Json.NET)处理序列化
Json.NET对MongoDB的BsonDocument支持更完善,步骤如下:
- 安装NuGet包:
Microsoft.AspNetCore.Mvc.NewtonsoftJson - 在
Program.cs中配置替换默认序列化器:
builder.Services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; });
方案3:忽略该属性的序列化
如果前端不需要UserDocument数据,直接标记该属性忽略序列化:
[BsonElement("UserDocument")] [JsonIgnore] // 使用System.Text.Json的特性,若用Json.NET则用[Newtonsoft.Json.JsonIgnore] public dynamic UserDocument { get; set; };
方案4:自定义System.Text.Json转换器
编写自定义转换器处理BsonDocument的序列化/反序列化:
public class BsonDocumentConverter : JsonConverter<BsonDocument> { public override BsonDocument Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var jsonDoc = JsonDocument.ParseValue(ref reader); return BsonDocument.Parse(jsonDoc.RootElement.GetRawText()); } public override void Write(Utf8JsonWriter writer, BsonDocument value, JsonSerializerOptions options) { var jsonStr = value.ToJson(); writer.WriteRawValue(jsonStr); } }
然后在Program.cs中注册转换器:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new BsonDocumentConverter()); });
辅助排查步骤
开启详细日志以捕获序列化时的具体错误:
在appsettings.json中调整日志级别:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning", "System.Text.Json": "Debug" } } }
内容的提问来源于stack exchange,提问作者skillworks
相关产品推荐
相关产品推荐

