.net core 将JsonPatchDocument与Blazor一起使用时出现意外错误
我使用Blazor WebAssembly(WASM)客户端通过.NET核心REST API执行更新。为此,我通过HTTP补丁请求发送一个.net core 将JsonPatchDocument与Blazor一起使用时出现意外错误,.net-core,asp.net-core-webapi,blazor,blazor-client-side,blazor-webassembly,.net Core,Asp.net Core Webapi,Blazor,Blazor Client Side,Blazor Webassembly,我使用Blazor WebAssembly(WASM)客户端通过.NET核心REST API执行更新。为此,我通过HTTP补丁请求发送一个JsonPatchDocument,其中T是我的应用程序的数据传输对象(DTO)之一 它不起作用。我在Blazor应用程序中返回了一个500内部服务器错误状态代码。我在《邮递员》中得到了更多的细节,但还不足以让我理解这个问题 以下是我的Blazor WASM应用程序中的调用代码: @code { [Parameter] public int BookId {
JsonPatchDocument
,其中T
是我的应用程序的数据传输对象(DTO)之一
它不起作用。我在Blazor应用程序中返回了一个500内部服务器错误状态代码。我在《邮递员》中得到了更多的细节,但还不足以让我理解这个问题
以下是我的Blazor WASM应用程序中的调用代码:
@code
{
[Parameter]
public int BookId { get; set; } = 101;
private async Task HandleClickAsync()
{
string newTitle = "How to make JsonPatchDocument work with Blazor - Second Edition";
var patchDocument = new JsonPatchDocument<Book>()
.Replace(c => c.Title, newTitle);
var json = JsonSerializer.Serialize(patchDocument);
var content = new StringContent(json, Encoding.UTF8, "application/json-patch+json");
var response = await HttpClient.PatchAsync($"https://localhost:44367/api/books/{BookId}", content);
if (response.IsSuccessStatusCode)
{
// Handle success
}
else if (response.StatusCode == HttpStatusCode.NotFound)
{
// Handle not found
}
else
{
// Handle unexpected failures
}
}
}
当序列化为JSON时,我发送的修补程序文档如下所示:
{"Operations":[{"value":"How to make JsonPatchDocument work with Blazor - Second Edition","OperationType":2,"path":"/Title","op":"replace","from":null}],"ContractResolver":{}}
public static class HttpClientExtensions
{
public static async Task<HttpResponseMessage> PatchAsync<T>(this HttpClient client,
string requestUri,
JsonPatchDocument<T> patchDocument)
where T : class
{
var writer = new StringWriter();
var serializer = new JsonSerializer();
serializer.Serialize(writer, patchDocument);
var json = writer.ToString();
var content = new StringContent(json, Encoding.UTF8, "application/json-patch+json");
return await client.PatchAsync(requestUri, content);
}
我在《邮递员》中看到的错误细节是:
System.NotSupportedException: Deserialization of interface types is not supported. Type 'Newtonsoft.Json.Serialization.IContractResolver'
at System.Text.Json.ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(Type invalidType)
at System.Text.Json.JsonSerializer.HandleStartObject(JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location where exception was thrown ---
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.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Accept-Encoding: gzip, deflate, br
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 175
Content-Type: application/json
Host: localhost:44367
User-Agent: PostmanRuntime/7.26.3
Postman-Token: b4444f41-b80f-4ef5-92d5-2416d68d471e
System.NotSupportedException:不支持接口类型的反序列化。键入“Newtonsoft.Json.Serialization.IContractResolver”
位于System.Text.Json.ThrowHelper.ThrownNotSupportedException_反序列化CreateObjectDelegateIsNull(类型invalidType)
位于System.Text.Json.JsonSerializer.handleStarObject(JsonSerializerOptions选项,ReadStack和state)
位于System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions选项、Utf8JsonReader和reader、ReadStack和ReadStack)
位于System.Text.Json.JsonSerializer.ReadCore(JsonReaderState和readerState、布尔值isFinalBlock、ReadOnlySpan`1缓冲区、JsonSerializerOptions选项、ReadStack和ReadStack)
在System.Text.Json.JsonSerializer.ReadAsync[TValue](流utf8Json,类型returnType,JsonSerializerOptions选项,CancellationToken CancellationToken)
位于Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext,编码)
位于Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext,编码)
位于Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext绑定上下文)
位于Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext ActionContext、IModelBinder modelBinder、IValueProvider valueProvider、ParameterDescriptor参数、ModelMetadata元数据、对象值)
在Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.c_uuDisplayClass0_0.d.MoveNext()中
---来自引发异常的上一个位置的堆栈结束跟踪---
在Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g_u等待| 13_0(ControllerActionInvoker invoker,Task lastTask,State next,Scope Scope,Object State,Boolean isCompleted)
在Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g_|24_0(ResourceInvoker invoker、Task lastTask、State next、Scope Scope、Object State、Boolean isCompleted)
位于Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed上下文)
位于Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(状态和下一步、范围和范围、对象和状态、布尔值和isCompleted)
在Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()中
---来自引发异常的上一个位置的堆栈结束跟踪---
在Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g|u waiting | 17|0(ResourceInvoker invoker,Task Task,IDisposable作用域)
位于Microsoft.AspNetCore.Routing.EndpointMiddleware.g_uwaitRequestTask | 6_0(端点、任务请求任务、ILogger记录器)
位于Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext上下文)
位于Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext上下文)
位于Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext上下文)
标题
=======
接受:*/*
接受编码:gzip,deflate,br
缓存控制:没有缓存
连接:保持活力
内容长度:175
内容类型:application/json
主机:本地主机:44367
用户代理:PostmanRuntime/7.26.3
邮递代币:b4444f41-b80f-4ef5-92d5-2416d68d471e
我的任何项目都不直接依赖Newtonsoft。不过,我不知道我引用的Microsoft库是否依赖于Newtonsoft。这个错误表明他们可能会这样做
在GitHub上的这个小存储库中可以观察到这种行为:
有人知道它为什么不工作和/或什么能解决它吗
谢谢我设法解决了这个难题,Pavel和Enet的意见非常有用,谢谢 对于其他有相同问题的人,您需要了解以下内容来解决此问题:
Newtonsoft.Json
移动到System.Text.Json
的努力还没有完成。包Microsoft.AspNetCore.JsonPatch
仍然依赖于Newtonsoft.Json
Microsoft.AspNetCore.JsonPatch
切换到System.Text.Json
需要付出太多的努力
JsonPatch
es,但不用于Web API/server项目的Startup
类中应使用的任何其他内容。请特别注意GetJsonPatchInputFormatter
helper方法的使用,该方法在Startup.ConfigureServices
System.Text.Json
序列化JsonPatch
,它会在Json字符串的末尾添加一个空的ContractResolver
对象(看起来像,“ContractResolver”:{}
),它在服务器端中断。由于某些原因,该请求与您所做的任何控制器路由都不匹配
Newtonsoft.Json
。你不必事事都用它;你只需要使用
System.NotSupportedException: Deserialization of interface types is not supported. Type 'Newtonsoft.Json.Serialization.IContractResolver'
at System.Text.Json.ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(Type invalidType)
at System.Text.Json.JsonSerializer.HandleStartObject(JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadCore(JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& readStack)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location where exception was thrown ---
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.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Accept-Encoding: gzip, deflate, br
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 175
Content-Type: application/json
Host: localhost:44367
User-Agent: PostmanRuntime/7.26.3
Postman-Token: b4444f41-b80f-4ef5-92d5-2416d68d471e
public static class HttpClientExtensions
{
public static async Task<HttpResponseMessage> PatchAsync<T>(this HttpClient client,
string requestUri,
JsonPatchDocument<T> patchDocument)
where T : class
{
var writer = new StringWriter();
var serializer = new JsonSerializer();
serializer.Serialize(writer, patchDocument);
var json = writer.ToString();
var content = new StringContent(json, Encoding.UTF8, "application/json-patch+json");
return await client.PatchAsync(requestUri, content);
}