通过RESTful API获取Acumatica中的联系人

通过RESTful API获取Acumatica中的联系人,acumatica,filemaker,Acumatica,Filemaker,@HB_ACUMATICA等 在过去的几个月里,我一直致力于将客户的FileMaker数据库与Acumatica集成。我能够访问(获取/放置)各种表(实体),例如PROJECT和CUSTOMER,但是CONTACT实体总是产生错误。比如说, https://mydomain.acumatica.com/entity/Default/18.200.001/Customer[工作正常] https://mydomain.acumatica.com/entity/Default/18.200.001/

@HB_ACUMATICA等

在过去的几个月里,我一直致力于将客户的FileMaker数据库与Acumatica集成。我能够访问(获取/放置)各种表(实体),例如PROJECT和CUSTOMER,但是CONTACT实体总是产生错误。比如说,


https://mydomain.acumatica.com/entity/Default/18.200.001/Customer
[工作正常]


https://mydomain.acumatica.com/entity/Default/18.200.001/Contact
[始终是一个错误500]

**[编辑:上述示例当然不完整,除非试图查找“所有”联系人记录。在测试中,我指定了实际的联系人ID,如

https://mydomain.acumatica.com/entity/Default/18.200.001/Customer/Nobody
其中“Nobody”是一个真实的联系人ID……或者我被引导相信……请参见下面我的答案]**

我在文档中看到的每一处都表明“Contact”是实体的专有名称。我做错了什么

非常感谢。
--埃里克

这是一个尚未解决的已知问题。web服务调用返回的错误消息为:

{
    "message": "An error has occurred.",
    "exceptionMessage": "Optimization cannot be performed.The following fields cause the error:\r\nAddressValidated: View AddressCurrent has BQL delegate\r\n",
    "exceptionType": "PX.Api.ContractBased.OptimizedExport.CannotOptimizeException",
    "stackTrace": "   at PX.Api.ContractBased.OptimizedExport.NotWorkingOptimizedExportProvider.get_CanOptimize() in C:\\Bld2\\AC-FULL2017R21-JOB1\\sources\\NetTools\\PX.Api.ContractBased\\OptimizedExport\\NotWorkingOptimizedExportProvider.cs:line 84\r\n   at PX.Api.ContractBased.EntityService.GetList(ISystemContract systemContract, String version, String name, EntityImpl entity, Boolean returnFullEntities, CbOperationContext operationContext, Boolean ignoreValueFields, PXGraph graph) in C:\\Bld2\\AC-FULL2017R21-JOB1\\sources\\NetTools\\PX.Api.ContractBased\\EntityService.cs:line 116\r\n   at PX.Api.ContractBased.Soap.SoapFacadeBase.GetListImpl(Entity entity, Boolean returnFullEntities) in C:\\Bld2\\AC-FULL2017R21-JOB1\\sources\\NetTools\\PX.Api.ContractBased\\Soap\\SoapFacadeBase.cs:line 83\r\n   at PX.Api.ContractBased.SystemContracts.V2.RestController.GetList(String objectName, String select, String filter, String expand, String custom, Nullable`1 skip, Nullable`1 top) in C:\\Bld2\\AC-FULL2017R21-JOB1\\sources\\NetTools\\PX.Api.ContractBased\\SystemContracts\\V2\\RestController.cs:line 247\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(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__0.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__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.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>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.<ExecuteActionFilterAsyncCore>d__0.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__2.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__2.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__0.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__0.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__1.MoveNext()"
}

正如Samvel Petrosov提到的,您还可以扩展端点并从那里删除
AddressValidated
字段(这似乎不适用于来自默认端点的字段,仅用于自定义字段):

使用这种方法,您必须将URL中的端点更改为扩展端点名称(本例中为“DefaultPlus”):

啊哈!谢谢大家,这些潜在的有用信息可能会在接下来的时间里派上用场。然而,这些问题和我对不做正确事情的担忧都变成了“红鲱鱼”。针灸在遵循自己的习惯方面奇怪的前后矛盾再一次让我困惑

我试图以与Elsewhare相同的格式执行请求,例如。
https://mydomain.acumatica.com/entity/Default/18.200.001/Customer/ACME001
(其中“ACME001”是一个真实的客户ID),工作正常,一切正常。鉴于
https://mydomain.acumatica.com/entity/Default/18.200.001/Contact/Nobody
(其中“Nobody”是真实的联系人ID)不起作用

为什么??尽管我对此持怀疑态度,并且有更好的判断,30年的数据库编程经验告诉我Acumatica的“ContactID”并不是唯一记录标识符的明智实现。。。我相信别人告诉我的。就在Element Properties inspector中,它说字段的真实名称(标记为“Contact ID”)实际上是“ContactID”

当我最终尝试另一种形式的查询时

https://mydomain.acumatica.com/entity/Default/18.200.001/Contact?$filter=LastName eq 'Wegweiser'&$select=FirstName,ContactID
我终于收到了告诉我真相的有效载荷: 不幸的是,根据惯例,在其他地方被识别为“ContactID”并被合理地视为唯一标识符的东西实际上是合理命名的“DisplayName” 正如人们所料,真正的“联系人ID”是真正的唯一ID

针灸是一种神奇的工具。它只是一个真正不同的动物,有许多头(或者一些可能是尾巴),伊姆霍


由HB_ACUMATICA编辑

查看
Contact.ContactID
字段定义,在
Contact
DAC中,它确实被声明为
整数
字段,并且没有一个会在屏幕上返回
字符串
显示值的自定义属性:

#region ContactID
public abstract class contactID : IBqlField { }

[PXDBIdentity(IsKey = true)]
[PXUIField(DisplayName = "Contact ID", Visibility = PXUIVisibility.Invisible)]
[PXPersonalDataWarning]
public virtual Int32? ContactID { get; set; }
#endregion
仅凭此DAC定义,屏幕上显示的字段是
String
类型而不是
Integer
类型确实是不一致的。对此行为的解释是,
联系人屏幕
使用
ContactMaint
图形,该图形使用
CacheAttached
机制重新定义了
Contact.ContactID
DAC字段:

[PXUIField(DisplayName = "Contact ID")]
[ContactSelector(true, typeof(ContactTypesAttribute.person), typeof(ContactTypesAttribute.employee))]
[PXMergeAttributes(Method = MergeMethod.Merge)]
public virtual void Contact_ContactID_CacheAttached(PXCache sender) { }
请注意,
Contact.ContactID
字段重新定义添加了
ContactSelector
属性,该属性在
Contact
DAC中不存在。快速查看该属性可以发现它正在使用
PXSelector
Description
字段在屏幕上显示
DisplayName
字符串,而不是
Integer
值。此替换仅用于在限制为
ContactMaint
图形的屏幕中显示,所有数据库操作仍然基于
Integer
。联系人选择器摘录:

public ContactSelectorAttribute(bool showContactsWithNullEmail, params Type[] contactTypes)
    : base(GetQuery(typeof(Contact.contactID), showContactsWithNullEmail, contactTypes))
{
    if (contactTypes == null || contactTypes.Length == 0)
        throw new ArgumentNullException(nameof(contactTypes));

    DescriptionField = typeof(Contact.displayName);         
}

REST web服务调用没有使用
Contact
DAC而不是
ContactMaint
图,这就是为什么它需要一个
Integer
而不是
String
值。

是否将ContactID作为参数传递?500响应通常包含一个带有错误描述的正文。您遇到了什么错误?似乎是因为AddressValidated上的委托,我将尝试创建一个答案,排除导致请求失败的字段。您是否尝试扩展服务端点,为Contact创建自定义端点,并仅添加所需字段,除了
默认地址->Validated
?完成此操作后,我可以从联系人终结点获取所有记录。@Rick,是的,我尝试了“,”例如(当存在ID为“Nobody”的联系人时)。从终结点删除
Validated
字段后,此错误消失。是的,我想知道为什么AddressValidated不会为单个实体返回。找出原因,未激活地址验证功能时,不会返回该字段。但这并不影响委托失败,我将更新我的答案以添加端点扩展选项。@SamvelPetrosov,我试图从扩展端点中删除该字段,但当我单击[X]时,字段旁边会出现一个红色的X。争吵并没有消失。如果我执行其他操作,X将消失(还没有“保存”选项)。mydomain.acumatica.com/entity/DefaultPlus/18.200.001/Contact/Nobody?$select=ContactID会产生相同的错误500I编辑您的答案以添加对联系人屏幕与REST Web服务中整数/字符串不匹配行为的解释。
[PXUIField(DisplayName = "Contact ID")]
[ContactSelector(true, typeof(ContactTypesAttribute.person), typeof(ContactTypesAttribute.employee))]
[PXMergeAttributes(Method = MergeMethod.Merge)]
public virtual void Contact_ContactID_CacheAttached(PXCache sender) { }
public ContactSelectorAttribute(bool showContactsWithNullEmail, params Type[] contactTypes)
    : base(GetQuery(typeof(Contact.contactID), showContactsWithNullEmail, contactTypes))
{
    if (contactTypes == null || contactTypes.Length == 0)
        throw new ArgumentNullException(nameof(contactTypes));

    DescriptionField = typeof(Contact.displayName);         
}