首页 > 解决方案 > 将 ASP.NET Core WebApi 项目从 2.2 更新到 3.0 导致 ExpandoObject JSON 序列化错误

问题描述

我的响应对象已从 MongoDB 加载,字段为 ExpandoObject,在更新到 dotnet core 3.0 后,我一直收到错误消息,例如“无法将类型为 'd__51' 的对象转换为类型 'System.Collections.IDictionaryEnumerator'”

An unhandled exception occurred while processing the request.
InvalidCastException: Unable to cast object of type '<GetExpandoEnumerator>d__51' to type 'System.Collections.IDictionaryEnumerator'.
System.Text.Json.JsonSerializer.HandleDictionary(JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state)

Stack Query Cookies Headers Routing
InvalidCastException: Unable to cast object of type '<GetExpandoEnumerator>d__51' to type 'System.Collections.IDictionaryEnumerator'.
System.Text.Json.JsonSerializer.HandleDictionary(JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state)
System.Text.Json.JsonSerializer.HandleObject(JsonPropertyInfo jsonPropertyInfo, JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state)
System.Text.Json.JsonSerializer.WriteObject(JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state)
System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, int originalWriterDepth, int flushThreshold, JsonSerializerOptions options, ref WriteStack state)
System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken)
Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|21_0(ResourceInvoker invoker, IActionResult result)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|29_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

标签: asp.net-core-3.0

解决方案


我发现这是因为微软在 dotnetcore3.0 中默认使用了自己的 JSON 库“System.Text.Json”。并且“System.Text.Json.JsonSerializer”无法序列化我们使用来自MongoDB.Driver的数据模型的动态“ExpendoObject”类型。

所以解决方案是将项目配置为使用 System.Text.Json 以外的 NewtonsoftJson。参考链接: https ://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio

1.安装NuGet包“Microsoft.AspNetCore.Mvc.NewtonsoftJson”(3.0.0)

2 在 Startup.cs 更新 configureServices 如下

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers().AddNewtonsoftJson(); 

    }

推荐阅读