【问题标题】:Setting null for single-valued navigation property using Xrm.WebApi使用 Xrm.WebApi 为单值导航属性设置 null
【发布时间】:2018-08-26 01:23:02
【问题描述】:

我们正在修复、重新设计旧的 JS Web 资源,以针对最新的 D365 v9 sdk 更改 w.r.t 客户端脚本 API 改进和弃用。

当使用 Xrm.WebApi 重写 web api 方法时,我们最终得到了这个拦截器。

场景设置null进行查找,并尝试了以下代码:

var data = {
    "abc_relatedentity@odata.bind": null
};

Xrm.WebApi.updateRecord("abc_entity", abc_entityid, data).then(successCallback, errorCallback);

这是抛出错误:

“'odata.bind' 实例或属性注释具有空值。在 OData 中,'odata.bind' 实例或属性注释必须具有非空字符串值。”

这个想法是淘汰下面多余的 XHR 请求代码。但这是我们现在唯一的解决方法(参考MSDN)。

var req = new XMLHttpRequest();
req.open("DELETE", Xrm.Utility.getGlobalContext().getClientUrl() + "/api/data/v9.0/accounts(recordGUID)/account_parent_account/$ref", true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function() {
    if (this.readyState === 4) {
        req.onreadystatechange = null;
        if (this.status === 204 || this.status === 1223) {
            //Success - No Return Data - Do Something
        } 
    }
};
req.send();

有人遇到过并处理过吗?我错过了什么吗?

【问题讨论】:

    标签: dynamics-crm microsoft-dynamics dynamics-crm-online dynamics-crm-webapi dynamics-crm-365-v9


    【解决方案1】:

    您必须使用 Delete 方法来删​​除查找值 格式如下: /api/data/v8.0/accounts(1DD18913-11CB-E511-80D2-C4346BDC11C1)/primarycontactid/$ref

    【讨论】:

    • @JimDaly-MSFT-这正是我们现在使用的,即 XMLHttpRequest 中的 DELETE 动词(我自己添加了问题)。我实际上正在寻找 Xrm.Webapi 版本
    • Xrm.WebApi 做了它该做的事,但它不包括你能做的所有事情。您仍然可以使用 XmlHttpRequest,而不受 Xrm.WebApi 的限制。在此处查看使用 Sdk.request 的 JavaScript 示例:docs.microsoft.com/en-us/powerapps/developer/… 您会在附近找到很多使用它的示例。
    • @JimDaly-MSFT- 好的,如果在这种情况下有任何开发,我将等待 Xrm.WebApi 的未来更新,直到那时我将使用我现在正在做的同样的事情。
    【解决方案2】:

    您应该尝试 Xrm.WebApi.online.execute 或 Xrm.WebApi.online.executeMultiple

    var Sdk = window.Sdk || {};
    
    
    /**
     * Request to execute an update operation
     */
    Sdk.UpdateRequest = function(entityName, entityId, payload) {
        this.etn = entityName;
        this.id = entityId;
        this.payload = payload;
    };
    
    // NOTE: The getMetadata property should be attached to the function prototype instead of the
    // function object itself.
    Sdk.UpdateRequest.prototype.getMetadata = function () {
        return {
            boundParameter: null,
            parameterTypes: {},
            operationType: 2, // This is a CRUD operation. Use '0' for actions and '1' for functions
            operationName: "Update",
        };
    };
    
    // Construct a request object from the metadata
    var payload = {
        "_abc_relatedentity_value": null 
    };
    var updateRequest = new Sdk.UpdateRequest("abc_entity", abc_entityid, payload);
    
    // Use the request object to execute the function
    Xrm.WebApi.online.execute(updateRequest).then(
        function (response) {
           console.log(response)
        },
        function(error) {
            console.log(error.message);
            // handle error conditions
        }
    );
    

    【讨论】:

      【解决方案3】:

      我认为将列设置为 null 就足够了,请确保您删除了 '@odata.bind'

      var 数据 = { “abc_relatedentity”:空 };

      这对我有用。

      【讨论】:

      • 是的,Dynamics web api 的最新发展可能允许这样做
      【解决方案4】:

      好消息!您可以在PATCH 请求中将查找字段设置为null,方法是将此标头添加到您的请求中。

      autodisassociate: true
      

      然后您可以使用类似的方法以任何方式更改您的查找字段:

      SetLookupField(requestBody, "systemusers", "msdfm_MyUser", null)
      // Or
      SetLookupField(requestBody, "systemusers", "msdfm_MyUser", "f5b0b514-aea8-ea11-a812-000d3a569fe1")
      
      // ...
      
      private static void SetLookupField(JObject requestBody, string typePlural, string name, string value)
      {
          if (!string.IsNullOrEmpty(value))
          {
              requestBody.Add($"{name}@odata.bind", $"/{typePlural}({value})");
          }
          else
          {
              requestBody.Add($"_{name.ToLower()}_value", null);
          }
      }
      

      无论如何,OP 都使用XMLHttpRequest,所以我想,在这里使用PATCH 的方法很重要。

      【讨论】:

      • 很高兴知道,感谢您的回答。我最初的要求是让 XHR 退役并转移到 Xrm.WebApi,它仍然悬而未决。
      • 没有记录或支持使用此自动取消关联标头。
      【解决方案5】:

      要在查找中设置 null,请使用:

      var data = { _[LookupFieldName]_value : null } 
      Xrm.WebApi.updateRecord("abc_entity", abc_entityid, data).then(successCallback, errorCallback
      

      例如要删除您需要使用的contact.parentcustomerid 字段值:

      var data = {};
      data._parentcustomerid_value = null
      var t = await Xrm.WebApi.updateRecord("contact", "{0200E6F5-1D21-E811-A954-0022480042B3}", data)
      

      【讨论】:

      • 事实上,这仍然失败,错误“属性_abc_relatedentity_value不能更新为null。引用属性只能删除。”
      【解决方案6】:

      我刚刚在 v9.1.0.3832 中尝试过 var data = { _[LookupFieldName]_value : null } 为我工作。

      var data =
      {
        "statecode": 1,
        "*_myprefix_mylookupfieldname_value*": null
      }
      Xrm.WebApi.updateRecord("*entityName*", *recordId*, data);
      

      【讨论】:

      • 我刚刚在 1710 (9.1.0.4416) 中进行了测试,遇到了同样的错误“无法将属性 _abc_relatedentity_value 更新为 null。只能删除引用属性。”
      • _[LookupFieldName]_value 字段为只读计算字段
      • @JimDaly-MSFT- 谢谢吉姆,你知道为什么有些人一直说它正在工作 - community.dynamics.com/crm/f/microsoft-dynamics-crm-forum/…
      • 这可能取决于您是使用客户端 Xrm.WebApi 方法还是直接使用 Web API。客户端 API 可能正在使用其他人提到的 autodisassociate 标头。这不是受支持的标头。它有效,但不受支持。我们正在努力提供支持的选项。删除时,不会有任何通知。因此,使用风险自负 - 或仅依赖 Xrm.WebAPI 方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      • 2013-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-07
      相关资源
      最近更新 更多