通过API在Microsoft Dynamics CRM中创建联系人实体的注释

25
这个问题涉及到我通过API调用的Microsoft Dynamics CRM 2015。我创建联系人实体:
POST [organization URI]/api/data/contacts
Content-Type: application/json; charset=utf-8
Accept: application/json
{
    "emailaddress1": "myemail@example.com",
}

它可以正常工作,我在登录面板后看到了新记录。我可以通过API调用它:

[organization URI]/api/data/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)
{
  "@odata.context":"[organization URI]/api/data/$metadata#contacts/$entity",
  "@odata.etag":"W/\"460199\"",
  ...
  "contactid":"f76e4e7c-ea61-e511-80fd-3863bb342b00",
  "emailaddress1":"myemail@example.com",
  ....
}

我接下来要做的事情是为该联系人添加关联的注释记录。 按照指南所述,我调用:

POST [organization URI]/api/data/annotations
Content-Type: application/json; charset=utf-8
Accept: application/json
{
    "notetext": "TEST",
    'contact@odata.bind': 'contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)'
}

但它返回400错误:

在有效负载中找不到仅具有属性注释但没有属性值的“contact”未声明属性。 在OData中,只有已声明的导航属性和已声明的命名流可以表示为没有值的属性。

当我调用时:

POST [organization URI]/api/data/annotations
Content-Type: application/json; charset=utf-8
Accept: application/json
{
    "notetext": "TEST",
}

新实体已创建,但没有与联系人相关联。

如何正确组合此POST请求?我在这里缺少什么? 我怀疑contact@odata.bind应该以某种不同的方式呈现,我尝试了contactid@odata.bindobject@odata.bindobjectid@odata.bind,但没有效果。

有任何想法吗?


你为什么使用 Web API 预览而不是 REST 端点? - Guido Preite
代码应该是 "objectid@data.bind": "/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)",请注意在联系人前面加上斜杠和引号(以防万一)。 - Guido Preite
1
@GuidoPreite 我已经尝试过了,错误信息是:“一个仅在有效负载中具有属性注释但未声明为 'Edm.Guid' 类型的属性 'objectid'。在 OData 中,只有导航属性和命名流可以表示为没有值的属性。” - maicher
8个回答

24

不要使用objectid@odata.bind,而是使用objectid_contact@odata.bind。这样可以得到以下结果:

"objectid_contact@odata.bind": "/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)"

要获取属性列表,请查看文档中的单值导航属性。


3
这个回答比已接受的回答更好,因为它只使用了一个调用。我猜"_contact"(或类似的东西)的添加取决于当前记录是父记录还是子记录。 - zabby
1
我认为这是因为它特定于有关注释的领域,可以查找各种实体。因此,_contact取决于您希望将其设置为哪个实体(始终是notes regarding字段的objectid_entityname)。 - Justin
1
事实上,逻辑名称和导航属性名称不一致,因此检查文档是必要的。此外,我还必须删除值中的前导斜杠,因此要指定“businessunitid”的值,我必须使用:"businessunitid_businessunit@odata.bind": "businessunits(b6c0d6c6-a07f-e611-80e8-c4346bc49e60)" - Nathan
1
除此之外,我发现属性的大小写也很重要。例如,我有一个“myproj_myattribute@odata.bind”(失败了),而“myproj_MyAttribute@odata.bind”则是在CRM GUI中反映的方式(这个可以正常工作)。 - Mr Moose
我必须使用字段“模式名称”,它是大小写敏感的! - Anderson Luiz Ferrari

10

第一部分:
MS Docs 参考:深度插入

您可以通过将它们定义为导航属性值来创建相关实体。这被称为深度插入。 与基本创建一样,响应OData-EntityId标头包含已创建实体的Uri。未返回所创建相关实体的URI。

以下代码用于创建账户(1)、创建+关联主要联系人(2)、创建并关联机会(3)以及创建+关联任务(4)

POST [Organization URI]/api/data/v8.2/accounts HTTP/1.1
Content-Type: application/json; charset=utf-8
OData-MaxVersion: 4.0
OData-Version: 4.0
Accept: application/json

{
 "name": "Sample Account",
 "primarycontactid":
 {
     "firstname": "John",
     "lastname": "Smith"
 },
 "opportunity_customer_accounts":
 [
  {
      "name": "Opportunity associated to Sample Account",
      "Opportunity_Tasks":
      [
       { "subject": "Task associated to opportunity" }
      ]
  }
 ]
}

第二部分:
将注释与联系人相关联使用以下语法。

note["objectid_contact@odata.bind"] = "/contacts(C5DDA727-B375-E611-80C8-00155D00083F)";

参考SO链接博客

第三部分:
回答你在另一个关于annotation_id_from_first_request的答案中的评论:

要从上次请求的响应中获取创建的记录ID,您可以像下面这样解析:

                //get Response from Created Record
                entityIdWithLink = XMLHttpRequest.getResponseHeader("OData-EntityId");
 
                //get EntityId from ResponseHeader of Created Record  
                getEntityId = entityIdWithLink.split(/[()]/);
                getEntityId = getEntityId[1];

您可以阅读更多

您可以编写POST请求,以便从创建的记录返回数据,并具有201(已创建)状态。
要获得此结果,必须在请求标头中使用return=representation首选项。 要控制返回哪些属性,请将$select查询选项附加到实体集的URL后面。
如果使用了$expand查询选项,则将被忽略。 以这种方式创建实体时,不会返回包含指向已创建记录的URI的OData-EntityId标头。

注意:此功能是在Dynamics 365的2016年12月更新中添加的。

MS Docs参考:带有返回数据的创建

更新:
如果有人正在寻找可用于深度插入记录+注释的工作负载示例,则以下内容来自我的项目:

data = {
        "new_attribute1": "test attribute 1",
        "new_attribute2": "test attribute 2",
        "new_comments": "test comments",
        "new_recordurl": recordURL,
        "new_feedback_Annotations":
            [
                {
                    "notetext": "Screenshot attached",
                    "subject": "Attachment",
                    "filename": file.name,
                    "mimetype": file.type,
                    "documentbody": base64str,
                }
            ]
    };

9
我已经找到了这个有效的解决方法,但需要进行两次请求:
POST [organization URI]/api/data/annotations
Content-Type: application/json; charset=utf-8
Accept: application/json
{
    "notetext": "TEST"
}

POST [organization URI]/api/data/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)/Contact_Annotation/$ref
Content-Type: application/json; charset=utf-8
Accept: application/json
{
    "@odata.id": "[organization URI]/annotations(annotation_id_from_first_request)"
}

编辑:

annotation_id_from_first_request 值取自第一个请求的响应。


从第一个请求的响应开始。 - maicher

5

这个答案适用于Web API的使用:

如果引用属性已经使用大写字母定义,那么在更新和插入时必须使用大写字母。查看主要实体属性列表中的模式名称。

假设您有一个名为的实体,它引用了账户实体,并将其命名为,模式名称变为,则您需要将其引用为:

"myprefix_AccountId@odata.bind":"/accounts(f76e4e7c-ea61-e511-80fd-000000000000)"

myprefix_AccountId中的大写字母 A 和大写字母 I 很重要,如果这是架构名称的定义方式。


这也是Dynamics CRM Ribbon Workbench的一个问题。 - Christo

4
我使用以下 C# 代码用于创建和链接(Task.Await 部分并不很聪明,所以请小心):
dynamic testAno = new ExpandoObject();
testAno.NoteText = "Hello World!";
testAno.Subject = "Note Subject";

dynamic refAccount = new ExpandoObject();
refAccount.LogicalName = "account";
refAccount.Id = "003CCFC2-4012-DE11-9654-001F2964595C";

testAno.ObjectId = refAccount;
testAno.ObjectTypeCode = refAccount.LogicalName;

var demo = JsonConvert.SerializeObject(testAno);

HttpContent content = new StringContent(demo, Encoding.UTF8, "application/json");

var handler = new HttpClientHandler { UseDefaultCredentials = true };

HttpClient client = new HttpClient(handler);
var test = client.PostAsync(new Uri("http://crm/.../XRMServices/2011/OrganizationData.svc/AnnotationSet"), content).Result;

JSON看起来像这样:
{"NoteText":"Hello World!",
 "Subject":"Note Subject",
 "ObjectId": {"LogicalName":"account",
              "Id":"003CCFC2-4012-DE11-9654-001F2964595C"}
,"ObjectTypeCode":"account"}

1
你可以使用以下内容。
'contactid_contact@odata.bind': '/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)'

在大多数记录中,您将获得_contactid_value作为参数名称。因此,您必须像contactid_entityname@odata.bind这样传递参数,并在值中传递“EntitySetName”,它将是contacts和GUID。'/EntitySetName(GUID)' 因此,值将为'/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)'

0

可能有点晚了,但是以下链接中的答案非常好地解释了绑定的工作原理。

基本上,您需要使用字段模式名称和后缀@odata.bind,值为"/entityschemaname(recordGUID)"。请记住,entityschemaname 需要有一个's',而 recordGUID 不应该有花括号。

如需更多信息,请访问下面的链接,我从中获取了这些信息

'通过 Web API 创建记录时出现未声明的属性'


0
如果您使用OData,那么可以这样做...
在您的注释数据模型中:
[DataContract(Name = "annotations")]
public record Annotation
{
    [DataMember(Name = "objectid_rd_servicerequestsession")]
    public ServiceRequestSession ObjectId { get; set; } = default!;

    [DataMember(Name = "objecttypecode")]
    public string ObjectTypeCode { get; set; } = default!;

其中rd_servicerequestsession是您的实体名称。然后,您只需要创建一个新的注释对象Annotation object

    var annotation = new Annotation
    {
        ObjectId = serviceRequestSession,
        ObjectTypeCode = "rd_servicerequestsession",

只需调用InsertEntry方法即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接