.NET5 JsonPatchDocument.ApplyTo 添加或替换时抛出
.NET5 JsonPatchDocument.ApplyTo throws when add or replace
我的 JsonPatchDocument 对象有问题,它可以从字段中删除值,但不能 add/replace 它。
我的控制器代码如下:
[HttpPatch]
[Route("{layersGroupId}")]
public async Task<ActionResult> Patch([FromServices] IMediator mediator,
[FromBody] List<Operation<LayerGroup>> operations,
Guid layersGroupId,
CancellationToken cancellationToken)
{
await mediator.Send(new PatchLayersGroupCommand
{
LayersGroupId = layersGroupId,
JsonPatch = new JsonPatchDocument<LayerGroup>(operations, new DefaultContractResolver())
}, cancellationToken);
return Ok();
}
处理程序中的代码:
var layersGroup = await databaseContext.UsersLayersViews
.Where(x => x.UserId == identity.Current.UserId && x.LayerGroupId == request.LayersGroupId)
.Select(x => x.LayerGroup)
.SingleOrDefaultAsync(cancellationToken);
if (layersGroup == null)
throw new ValidationException(ErrorCode.InvalidId, "Invalid layers group ID");
request.JsonPatch.ApplyTo(layersGroup); // Code throws here
例外情况是:
Unhandled JsonPatchException caught, none of known global handlers could apply
ExceptionDetail
{HResult: -2146233088, Message: 'The value ''"NewName"'' is invalid for target location.', Source: 'Microsoft.AspNetCore.JsonPatch', StackTrace: ' at Microsoft.AspNetCore.JsonPatch.Internal.ErrorReporter.<>c.<.cctor>b__1_0(JsonPatchError error)
at Microsoft.AspNetCore.JsonPatch.Adapters.ObjectAdapter.Replace(Operation operation, Object objectToApplyTo)
at Microsoft.AspNetCore.JsonPatch.Operations.Operation`1.Apply(TModel objectToApplyTo, IObjectAdapter adapter)
at Microsoft.AspNetCore.JsonPatch.JsonPatchDocument`1.ApplyTo(TModel objectToApplyTo, IObjectAdapter adapter)
at Microsoft.AspNetCore.JsonPatch.JsonPatchDocument`1.ApplyTo(TModel objectToApplyTo)
at DHIPL.UrbanTools.GIS.Api.UseCases.Groups.Put.RenameGroup.RenameLayersGroupCommandHandler.Handle(RenameLayersGroupCommand request, CancellationToken cancellationToken) in C:\Users\msty\source\repos\urban-tools-backend\src\Services\GIS\GIS.Api\UseCases\Groups\Put\RenameGroup\RenameLayersGroupCommandHandler.cs:line 36
at DHIPL.Core.Api.Behaviors.ValidatorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core.Api\Behaviors\ValidatorBehavior.cs:line 31
at DHIPL.Core.Api.Behaviors.TransactionBehavior`2.<>c__DisplayClass0_0.<<Handle>b__0>d.MoveNext() in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core.Api\Behaviors\TransactionBehavior.cs:line 14
--- End of stack trace from previous location ---
at DHIPL.Core.Transactions.TransactionHelper.Wrap[TResult](Func`1 action) in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core\Transactions\TransactionHelper.cs:line 51
at DHIPL.Core.Api.Behaviors.TransactionBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core.Api\Behaviors\TransactionBehavior.cs:line 14
at DHIPL.Core.Api.Behaviors.LoggingBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core.Api\Behaviors\LoggingBehavior.cs:line 32
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at DHIPL.UrbanTools.GIS.Api.Controllers.GroupController.PutRename(IMediator mediator, List`1 operations, Guid layersGroupId, CancellationToken cancellationToken) in C:\Users\msty\source\repos\urban-tools-backend\src\Services\GIS\GIS.Api\Controllers\GroupController.cs:line 41
at lambda_method668(Closure , Object )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
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.<InvokeFilterPipelineAsync>g__Awaited|19_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.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at DHIPL.Core.Api.Exceptions.CoreExceptionMiddleware.Invoke(HttpContext context) in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core.Api\Exceptions\CoreExceptionMiddleware.cs:line 30', FailedOperation: {…}, AffectedObject: {…}, Type: 'Microsoft.AspNetCore.JsonPatch.Exceptions.JsonPatchException'}
Internet 上没有关于此错误的单个 post。我现在很困惑。以前有人遇到过这样的问题吗?如何解决?
以防万一,PatchLayersGroupCommand 中有这些数据:
{
LayersGroupId: 'c36bb6c1-4be2-44b9-9239-d7e41d10ebaa',
JsonPatch: {
Operations: [
{
value: {
ValueKind: 'String',
_typeTag: 'JsonElement'
},
OperationType: 'Replace',
path: '/GroupName',
op: 'replace',
from: null,
_typeTag: 'Operation`1'
}
],
ContractResolver: {
DynamicCodeGeneration: false,
DefaultMembersSearchFlags: 'Instance, Public',
SerializeCompilerGeneratedMembers: false,
IgnoreSerializableInterface: false,
IgnoreSerializableAttribute: true,
IgnoreIsSpecifiedMembers: false,
IgnoreShouldSerializeMembers: false,
NamingStrategy: null,
_typeTag: 'DefaultContractResolver'
},
_typeTag: 'JsonPatchDocument`1'
},
_typeTag: 'RenameLayersGroupCommand'
}
使用 Microsoft.AspNetCore.Mvc.NewtonsoftJson
包启用对 JsonPatch
的支持。要启用此功能,应用必须:
安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 包。
更新项目的 Startup.ConfigureServices
方法以包含对 AddNewtonsoftJson
:
的调用
services
.AddControllers()
.AddNewtonsoftJson();
将其添加到服务后,直接从正文中获取 JsonPatchDocument<T>
,不要自己创建。 JsonPatch 现在应该可以工作了。
我的 JsonPatchDocument 对象有问题,它可以从字段中删除值,但不能 add/replace 它。
我的控制器代码如下:
[HttpPatch]
[Route("{layersGroupId}")]
public async Task<ActionResult> Patch([FromServices] IMediator mediator,
[FromBody] List<Operation<LayerGroup>> operations,
Guid layersGroupId,
CancellationToken cancellationToken)
{
await mediator.Send(new PatchLayersGroupCommand
{
LayersGroupId = layersGroupId,
JsonPatch = new JsonPatchDocument<LayerGroup>(operations, new DefaultContractResolver())
}, cancellationToken);
return Ok();
}
处理程序中的代码:
var layersGroup = await databaseContext.UsersLayersViews
.Where(x => x.UserId == identity.Current.UserId && x.LayerGroupId == request.LayersGroupId)
.Select(x => x.LayerGroup)
.SingleOrDefaultAsync(cancellationToken);
if (layersGroup == null)
throw new ValidationException(ErrorCode.InvalidId, "Invalid layers group ID");
request.JsonPatch.ApplyTo(layersGroup); // Code throws here
例外情况是:
Unhandled JsonPatchException caught, none of known global handlers could apply
ExceptionDetail
{HResult: -2146233088, Message: 'The value ''"NewName"'' is invalid for target location.', Source: 'Microsoft.AspNetCore.JsonPatch', StackTrace: ' at Microsoft.AspNetCore.JsonPatch.Internal.ErrorReporter.<>c.<.cctor>b__1_0(JsonPatchError error)
at Microsoft.AspNetCore.JsonPatch.Adapters.ObjectAdapter.Replace(Operation operation, Object objectToApplyTo)
at Microsoft.AspNetCore.JsonPatch.Operations.Operation`1.Apply(TModel objectToApplyTo, IObjectAdapter adapter)
at Microsoft.AspNetCore.JsonPatch.JsonPatchDocument`1.ApplyTo(TModel objectToApplyTo, IObjectAdapter adapter)
at Microsoft.AspNetCore.JsonPatch.JsonPatchDocument`1.ApplyTo(TModel objectToApplyTo)
at DHIPL.UrbanTools.GIS.Api.UseCases.Groups.Put.RenameGroup.RenameLayersGroupCommandHandler.Handle(RenameLayersGroupCommand request, CancellationToken cancellationToken) in C:\Users\msty\source\repos\urban-tools-backend\src\Services\GIS\GIS.Api\UseCases\Groups\Put\RenameGroup\RenameLayersGroupCommandHandler.cs:line 36
at DHIPL.Core.Api.Behaviors.ValidatorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core.Api\Behaviors\ValidatorBehavior.cs:line 31
at DHIPL.Core.Api.Behaviors.TransactionBehavior`2.<>c__DisplayClass0_0.<<Handle>b__0>d.MoveNext() in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core.Api\Behaviors\TransactionBehavior.cs:line 14
--- End of stack trace from previous location ---
at DHIPL.Core.Transactions.TransactionHelper.Wrap[TResult](Func`1 action) in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core\Transactions\TransactionHelper.cs:line 51
at DHIPL.Core.Api.Behaviors.TransactionBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core.Api\Behaviors\TransactionBehavior.cs:line 14
at DHIPL.Core.Api.Behaviors.LoggingBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core.Api\Behaviors\LoggingBehavior.cs:line 32
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)
at DHIPL.UrbanTools.GIS.Api.Controllers.GroupController.PutRename(IMediator mediator, List`1 operations, Guid layersGroupId, CancellationToken cancellationToken) in C:\Users\msty\source\repos\urban-tools-backend\src\Services\GIS\GIS.Api\Controllers\GroupController.cs:line 41
at lambda_method668(Closure , Object )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
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.<InvokeFilterPipelineAsync>g__Awaited|19_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.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at DHIPL.Core.Api.Exceptions.CoreExceptionMiddleware.Invoke(HttpContext context) in C:\Users\msty\source\repos\urban-tools-backend\src\Packages\DHIPL.Core.Api\Exceptions\CoreExceptionMiddleware.cs:line 30', FailedOperation: {…}, AffectedObject: {…}, Type: 'Microsoft.AspNetCore.JsonPatch.Exceptions.JsonPatchException'}
Internet 上没有关于此错误的单个 post。我现在很困惑。以前有人遇到过这样的问题吗?如何解决?
以防万一,PatchLayersGroupCommand 中有这些数据:
{
LayersGroupId: 'c36bb6c1-4be2-44b9-9239-d7e41d10ebaa',
JsonPatch: {
Operations: [
{
value: {
ValueKind: 'String',
_typeTag: 'JsonElement'
},
OperationType: 'Replace',
path: '/GroupName',
op: 'replace',
from: null,
_typeTag: 'Operation`1'
}
],
ContractResolver: {
DynamicCodeGeneration: false,
DefaultMembersSearchFlags: 'Instance, Public',
SerializeCompilerGeneratedMembers: false,
IgnoreSerializableInterface: false,
IgnoreSerializableAttribute: true,
IgnoreIsSpecifiedMembers: false,
IgnoreShouldSerializeMembers: false,
NamingStrategy: null,
_typeTag: 'DefaultContractResolver'
},
_typeTag: 'JsonPatchDocument`1'
},
_typeTag: 'RenameLayersGroupCommand'
}
使用 Microsoft.AspNetCore.Mvc.NewtonsoftJson
包启用对 JsonPatch
的支持。要启用此功能,应用必须:
安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson
NuGet 包。
更新项目的 Startup.ConfigureServices
方法以包含对 AddNewtonsoftJson
:
services
.AddControllers()
.AddNewtonsoftJson();
将其添加到服务后,直接从正文中获取 JsonPatchDocument<T>
,不要自己创建。 JsonPatch 现在应该可以工作了。