【问题标题】:Create annotation to a contact entity in Microsoft Dynamics CRM by API通过 API 在 Microsoft Dynamics CRM 中为联系人实体创建注释
【发布时间】:2015-12-22 01:18:14
【问题描述】:

这个问题与我通过 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",
  ....
}

接下来我要做的是添加与该联系人关联的注释记录。 关注guide我打电话:

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 错误:

未声明的属性“联系人”仅在有效负载中具有属性注释,但在有效负载中未找到属性值。在 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.bind、object@odata.bind、objectid@odata.bind - 但没有效果。

有什么想法吗?

【问题讨论】:

  • 您为什么使用 Web API 预览而不是 REST 端点?
  • 代码应为"objectid@data.bind": "/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)",注意联系人前的/和引号(以防万一)
  • @GuidoPreite 我试过了,错误信息是:A property 'objectid' which only has property annotations in the payload but no property value is declared to be of type 'Edm.Guid'. In OData, only navigation properties and named streams can be represented as properties without values.

标签: odata dynamics-crm microsoft-dynamics dynamics-crm-webapi microsoft-dynamics-webapi


【解决方案1】:

如果你使用 OData,那么你可以这样做......

在您的 Annotation 数据模型中:

[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对象

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

然后简单地调用 InsertEntry 方法。

【讨论】:

    【解决方案2】:

    第 1 部分:
    微软文档参考:Deep Insert

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

    下面的代码是创建Account (1)、create + associate Primary contact (2)、create & Associate Opportunity (3)和create + associate Task (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" }
          ]
      }
     ]
    }
    

    第 2 部分:
    将注释关联到联系人使用以下语法。

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

    参考SO link & blog

    第 3 部分:
    回答您对有关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];
    

    你可以read more

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

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

    MS 文档参考:Create with data returned

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

    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,
                    }
                ]
        };
    

    【讨论】:

      【解决方案3】:

      我正在使用这个 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"}
      

      【讨论】:

        【解决方案4】:

        这可能有点晚了,但以下链接中的答案解释了绑定如何真正有效地工作。

        基本上,您需要使用后缀为 @odata.bind 且值为 "/entityschemaname(recordGUID)" 的字段架构名称 strong> 请记住,entityschemaname 需要有一个 's',而 recordGUID 不应有大括号。

        有关更多信息,请点击下面的链接,我是从那里获得此信息的

        'An undeclared property' when trying to create record via Web API

        【讨论】:

          【解决方案5】:

          你可以使用以下。

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

          在大多数记录中,您将获得 _contactid_value 作为参数名称。所以你必须像contactid_entityname@odata.bind一样作为参数传递,并且在值中你必须传递'EntitySetName',它是contacts和GUID。 '/实体集名称(GUID)' 所以值将是'/contacts(f76e4e7c-ea61-e511-80fd-3863bb342b00)'

          【讨论】:

            【解决方案6】:

            此答案适用于 web api 使用:

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

            假设您有一个名为 myprefix_entity 的实体引用帐户实体,您将其命名为 Account,架构名称变为 myprefix_AccountId,您必须将其引用为:

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

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

            【讨论】:

            • 这也是用于 Dynamics CRM 的 Ribbon Workbench 的问题
            【解决方案7】:

            我发现这是可行的,但有两个请求:

            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 值取自第一个请求的响应。

            【讨论】:

            • 来自第一个请求的响应。
            【解决方案8】:

            您必须使用objectid_contact@odata.bind,而不是使用objectid@odata.bind。结果如下:

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

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

            【讨论】:

            • 这比接受的响应要好,因为它只使用 1 次调用。我猜添加“_contact”(或类似的东西)取决于当前记录是父母还是孩子。
            • 我相信这是因为这是特定于笔记上的相关字段,它可以查找各种实体。因此,_contact 取决于您希望为其设置的实体(对于有关字段的注释,始终为 objectid_entityname)。
            • 确实属性逻辑名称和导航属性名称不一致,所以检查文档是必不可少的。此外,我必须删除值中的前导斜杠,以便为“businessunitid”指定一个值,我必须使用:"businessunitid_businessunit@odata.bind": "businessunits(b6c0d6c6-a07f-e611-80e8-c4346bc49e60)"。
            • 除此之外,我发现属性的 case 也很重要。例如,我有“myproj_myattribute@odata.bind”(失败)与“myproj_MyAttribute@odata.bind”(这就是它在 CRM GUI 中的反映方式..这很有效)。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-07-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多