问题描述
我有一个使用 REST API 为项目任务创建两个账单的流程。特定供应商类别的供应商的第一张账单总是成功创建并且可以正常处理。针对不同供应商类别的供应商的第二个账单几乎总是失败,抛出 500 Internal Server 错误。它们都将相同的数据结构传递给相同的函数来创建账单,并且我比较了从结构中编组并传递给 API 的 JSON。它在结构上是相同的——只是值不同。这是我收到错误时的响应正文:
{
"message": "An error has occurred.","exceptionMessage": "Object reference not set to an instance of an object.","exceptionType": "System.NullReferenceException","stackTrace": " at PX.Api.ContractBased.SystemContracts.V2.RestController.PutEntity(EntityImpl entity,String select,String filter,String expand,String custom)\r\n at lambda_method(Closure,Object,Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__displayClass6_1.<GetExecutor>b__3(Object instance,Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext,IDictionary`2 arguments,CancellationToken cancellationToken)\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Filters.ActionFilterattribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Web.Http.Filters.ActionFilterattribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Filters.ActionFilterattribute.<ExecuteActionFilterasyncCore>d__5.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Filters.ActionFilterattribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Web.Http.Filters.ActionFilterattribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Filters.ActionFilterattribute.<ExecuteActionFilterasyncCore>d__5.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Filters.AuthorizationFilterattribute.<ExecuteAuthorizationFilterasyncCore>d__3.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext()\r\n--- End of stack trace from prevIoUs location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.dispatcher.HttpControllerdispatcher.<SendAsync>d__15.MoveNext()"
}
我正在记录传递给 API 调用的 JSON。奇怪的是,如果我通过 Postman 发送相同的 JSON,它会起作用。
这是我传递的 JSON。
{
"note": "Bill for Job Assignment","Amount": {
"value": 210
},"Date": {
"value": "2020-12-28"
},"DueDate": {
"value": "2021-01-27"
},"Hold": {
"value": "false"
},"LocationID": {
"value": "MAIN"
},"Terms": {
"value": "SCHEDULE"
},"Type": {
"value": "Bill"
},"vendor": {
"value": "V003700"
},"vendorRef": {
"value": "FC02000029"
},"Details": [
{
"Branch": {
"value": "EDS"
},"InventoryId": {
"value": "FEEFORSERVICE"
},"Project": {
"value": "V000026C000166"
},"ProjectTask": {
"value": "020000961900029"
},"Qty": {
"value": 6
},"UnitCost": {
"value": 35
}
}
],"custom": {
"Document": {
"AttributeDETAILLOC": {
"type": "CustomStringField","value": "1240 Jones Mill Rd"
},"AttributeENDTIME": {
"type": "CustomStringField","value": "00:00"
},"AttributeJOBDATE": {
"type": "CustomDateTimeField","value": "12/27/2020"
},"AttributeJOBNBR": {
"type": "CustomStringField","value": 9619
},"AttributeOFIDNBR": {
"type": "CustomStringField","value": "937"
},"AttributeOFCREMPNBR": {
"type": "CustomStringField","value": "280"
},"AttributevendORID": {
"type": "CustomStringField","value": "V003700"
},"AttributeEMPNAME": {
"type": "CustomStringField","value": "Jones,James Earl"
},"AttributeSTARTTIME": {
"type": "CustomStringField","value": "18:00"
}
}
}
}
我希望堆栈跟踪中的线索对比我更有经验的 Acumatica REST API 的人有意义。
解决方法
我能够解决问题。事实证明,该问题与与我创建的账单相关的项目任务状态的一些(秘密)变化有关。一旦我发布了一个法案,我就无法创建或发布另一个法案。在发布第二个账单之前,我添加了一个步骤,将项目任务的状态更改为“活动”(在添加第一个账单之前就是这样),并且成功了。
使用 REST API 的另一个未记录的要求。这涉及到大量的猜测,但是一旦你全部弄清楚了,它就很好用!