当我不使用 `System.IntPtr` 时,为什么 System.Text.Json 会为 `System.IntPtr` 抛出 `NotSupportedException`?
Why does System.Text.Json throw a `NotSupportedException` for `System.IntPtr` when I'm not using `System.IntPtr`?
我有一个 .NET Framework 4.8 / AngularJS 应用程序,我正在尝试将其升级到 .NET 6,以便我可以开始尝试更新的前端框架(如 Blazor)。升级一切顺利,但在从 Angular JS 代码调用我的 API 方法之一时,我一直看到此错误:
System.NotSupportedException: Serialization and deserialization of 'System.IntPtr' instances are not supported. Path: $.TargetSite.MethodHandle.Value.
---> System.NotSupportedException: Serialization and deserialization of 'System.IntPtr' instances are not supported.
at System.Text.Json.Serialization.Converters.UnsupportedTypeConverter`1.Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ThrowNotSupportedException(WriteStack& state, NotSupportedException ex)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCoreAsObject(Utf8JsonWriter writer, Object value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteCore[TValue](JsonConverter jsonConverter, Utf8JsonWriter writer, TValue& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Authorization: Negotiate TlRMTVNTUAADAAAAGAAYAHgAAABgAWABkAAAAAAAAABYAAAADgAOAFgAAAASABIAZgAAABAAEADwAQAAFYKI4goAYUoAAAAPV7Hpy762wOgD8P0Vp4p25WsAawBvAHoAbABlAHIASwBLAE8AWgBMAEUAUgAtAEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyKkYMRt+BEmGGiFVayCimwEBAAAAAAAAsRKCqZ8i2AHdnAn8ozInsAAAAAACABAAUABSAE8ATQBPAEQARQBMAAEAEgBLAEsATwBaAEwARQBSAC0ATAAEACIAYwBvAHIAcAAuAHAAcgBvAG0AbwBkAGUAbAAuAGMAbwBtAAMANgBLAEsATwBaAEwARQBSAC0ATAAuAGMAbwByAHAALgBwAHIAbwBtAG8AZABlAGwALgBjAG8AbQAFACIAYwBvAHIAcAAuAHAAcgBvAG0AbwBkAGUAbAAuAGMAbwBtAAcACACxEoKpnyLYAQYABAACAAAACAAwADAAAAAAAAAAAQAAAAAgAABZ/aEtx5BWovcqYmfEANzjrij27KQ+UdanKJzMjBJr2QoAEAAAAAAAAAAAAAAAAAAAAAAACQAcAEgAVABUAFAALwBsAG8AYwBhAGwAaABvAHMAdAAAAAAAAAAAAKxoJoGhKPec1JQ2hdsVSsQ=
Connection: keep-alive
Content-Length: 346
Content-Type: application/json;charset=UTF-8
Cookie: ai_user=r+bRv|2022-01-12T04:50:58.222Z
Host: localhost:42721
Referer: http://localhost:42721/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Origin: http://localhost:42721
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
我对这个错误感到困惑。 API 方法如下所示:
[HttpPost]
public IActionResult Validate([FromBody] ValidationDto dto)
{
try
{
...
}
catch (Exception ex)
{
return StatusCode((int)HttpStatusCode.InternalServerError, ex.InnermostException());
}
}
ValidationDto
class 看起来像这样:
public class ValidationDto
{
public Guid GuidProperty { get; set; }
public DateTime? NullableDateTimeProperty { get; set; }
public int IntegerProperty { get; set; }
public ValidationType EnumProperty { get; set; }
public bool BooleanProperty { get; set; }
}
ValidationType
枚举如下所示:
public enum ValidationType
{
FirstType,
SecondType,
ThirdType,
}
我指定的唯一 JSON 选项如下:
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
System.Text.Json
在哪里找到它无法反序列化的 IntPtr
?
首先,我建议您使用 Newtonsoft.Json 来避免所有这些奇怪的错误
using Newtonsoft.Json.Serialization;
builder.Services.AddControllers (
.AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver());
如果您决定使用 Newtonsoft,则必须将这些属性添加到枚举中
public enum ValidationType
{
[EnumMember(Value = "FirstType")]
FirstType,
[EnumMember(Value = "SecondType")]
SecondType,
ThirdType,
}
如果您继续 text.json 试试他们的枚举转换器
JsonSerializerOptions options = new JsonSerializerOptions{
Converters ={
new JsonStringEnumConverter( JsonNamingPolicy.CamelCase)
},
};
JsonSerializer.Serialize(data, options);
您的代码在序列化而非反序列化期间失败,因为您捕获了一些内部异常并尝试通过 return 在此处将其序列化为 System.Text.Json:
return StatusCode((int)HttpStatusCode.InternalServerError, ex.InnermostException());
遗憾的是,System.Text.Json 不支持异常序列化,请参阅 System.Text.Json - can't serialize exception #43026 and also the demo fiddle https://dotnetfiddle.net/RrlPQB。它专门尝试序列化 TargetSite.MethodHandle.Value
失败,实际上,IntPtr
.
如果你真的需要return所有的异常数据,你可以写一个custom JsonConverter<Exception>
。但是,将必要的信息 return 作为字符串或 DTO 会更容易,如下所示:
return StatusCode((int)HttpStatusCode.InternalServerError, ex.InnermostException().Message);
或
return StatusCode((int)HttpStatusCode.InternalServerError, ex.InnermostException().ToString());
甚至像这样的匿名类型 DTO:
return StatusCode((int)HttpStatusCode.InternalServerError, new { ex.InnermostException().Message, StackTrace = ex.InnermostException().StackTrace?.ToString()} );
有额外的选项来自定义 return 编辑异常的方式。
我有一个 .NET Framework 4.8 / AngularJS 应用程序,我正在尝试将其升级到 .NET 6,以便我可以开始尝试更新的前端框架(如 Blazor)。升级一切顺利,但在从 Angular JS 代码调用我的 API 方法之一时,我一直看到此错误:
System.NotSupportedException: Serialization and deserialization of 'System.IntPtr' instances are not supported. Path: $.TargetSite.MethodHandle.Value.
---> System.NotSupportedException: Serialization and deserialization of 'System.IntPtr' instances are not supported.
at System.Text.Json.Serialization.Converters.UnsupportedTypeConverter`1.Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ThrowNotSupportedException(WriteStack& state, NotSupportedException ex)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCoreAsObject(Utf8JsonWriter writer, Object value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteCore[TValue](JsonConverter jsonConverter, Utf8JsonWriter writer, TValue& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Authorization: Negotiate TlRMTVNTUAADAAAAGAAYAHgAAABgAWABkAAAAAAAAABYAAAADgAOAFgAAAASABIAZgAAABAAEADwAQAAFYKI4goAYUoAAAAPV7Hpy762wOgD8P0Vp4p25WsAawBvAHoAbABlAHIASwBLAE8AWgBMAEUAUgAtAEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyKkYMRt+BEmGGiFVayCimwEBAAAAAAAAsRKCqZ8i2AHdnAn8ozInsAAAAAACABAAUABSAE8ATQBPAEQARQBMAAEAEgBLAEsATwBaAEwARQBSAC0ATAAEACIAYwBvAHIAcAAuAHAAcgBvAG0AbwBkAGUAbAAuAGMAbwBtAAMANgBLAEsATwBaAEwARQBSAC0ATAAuAGMAbwByAHAALgBwAHIAbwBtAG8AZABlAGwALgBjAG8AbQAFACIAYwBvAHIAcAAuAHAAcgBvAG0AbwBkAGUAbAAuAGMAbwBtAAcACACxEoKpnyLYAQYABAACAAAACAAwADAAAAAAAAAAAQAAAAAgAABZ/aEtx5BWovcqYmfEANzjrij27KQ+UdanKJzMjBJr2QoAEAAAAAAAAAAAAAAAAAAAAAAACQAcAEgAVABUAFAALwBsAG8AYwBhAGwAaABvAHMAdAAAAAAAAAAAAKxoJoGhKPec1JQ2hdsVSsQ=
Connection: keep-alive
Content-Length: 346
Content-Type: application/json;charset=UTF-8
Cookie: ai_user=r+bRv|2022-01-12T04:50:58.222Z
Host: localhost:42721
Referer: http://localhost:42721/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Origin: http://localhost:42721
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
我对这个错误感到困惑。 API 方法如下所示:
[HttpPost]
public IActionResult Validate([FromBody] ValidationDto dto)
{
try
{
...
}
catch (Exception ex)
{
return StatusCode((int)HttpStatusCode.InternalServerError, ex.InnermostException());
}
}
ValidationDto
class 看起来像这样:
public class ValidationDto
{
public Guid GuidProperty { get; set; }
public DateTime? NullableDateTimeProperty { get; set; }
public int IntegerProperty { get; set; }
public ValidationType EnumProperty { get; set; }
public bool BooleanProperty { get; set; }
}
ValidationType
枚举如下所示:
public enum ValidationType
{
FirstType,
SecondType,
ThirdType,
}
我指定的唯一 JSON 选项如下:
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
System.Text.Json
在哪里找到它无法反序列化的 IntPtr
?
首先,我建议您使用 Newtonsoft.Json 来避免所有这些奇怪的错误
using Newtonsoft.Json.Serialization;
builder.Services.AddControllers (
.AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver());
如果您决定使用 Newtonsoft,则必须将这些属性添加到枚举中
public enum ValidationType
{
[EnumMember(Value = "FirstType")]
FirstType,
[EnumMember(Value = "SecondType")]
SecondType,
ThirdType,
}
如果您继续 text.json 试试他们的枚举转换器
JsonSerializerOptions options = new JsonSerializerOptions{
Converters ={
new JsonStringEnumConverter( JsonNamingPolicy.CamelCase)
},
};
JsonSerializer.Serialize(data, options);
您的代码在序列化而非反序列化期间失败,因为您捕获了一些内部异常并尝试通过 return 在此处将其序列化为 System.Text.Json:
return StatusCode((int)HttpStatusCode.InternalServerError, ex.InnermostException());
遗憾的是,System.Text.Json 不支持异常序列化,请参阅 System.Text.Json - can't serialize exception #43026 and also the demo fiddle https://dotnetfiddle.net/RrlPQB。它专门尝试序列化 TargetSite.MethodHandle.Value
失败,实际上,IntPtr
.
如果你真的需要return所有的异常数据,你可以写一个custom JsonConverter<Exception>
。但是,将必要的信息 return 作为字符串或 DTO 会更容易,如下所示:
return StatusCode((int)HttpStatusCode.InternalServerError, ex.InnermostException().Message);
或
return StatusCode((int)HttpStatusCode.InternalServerError, ex.InnermostException().ToString());
甚至像这样的匿名类型 DTO:
return StatusCode((int)HttpStatusCode.InternalServerError, new { ex.InnermostException().Message, StackTrace = ex.InnermostException().StackTrace?.ToString()} );