在新打开的 Web 资源中使用 Xrm.WebApi 方法 window

Using Xrm.WebApi method in Web Resource opened in a new window

我在新 window 中打开了一个 HTML 网络资源,使用:

Xrm.Navigation.openWebResource(webResource, windowOptions, data);

这是一个 HTML 网络资源,它正在头部加载 ClientObject

<script type="text/javascript" src="../../../ClientGlobalContext.js.aspx" ></script>

然后我有一些 JavaScript 正在尝试检索 Contact

var contactId = "8553DA63-11C9-E711-A824-000D3AE0CB84";
var promise = Xrm.WebApi.retrieveRecord("contact", contactId, "$select=contactid,firstname,lastname");`

但这是失败。我已经跟踪到 Xrm.WebApi 方法,发现错误是当它试图将 "contact" 解析为 Set Name

Code from Global.ashx

getEntitySetName: function(logicalName) {
    Mscrm.Utilities.addTelemetryLog("Xrm.Utility.getEntitySetName");
    var $v_0 = window.ENTITY_SET_NAMES || window.top.ENTITY_SET_NAMES;
    if (IsNull(this.H_1) && !isNullOrEmptyString($v_0))
        this.H_1 = JSON.parse($v_0);
    return this.H_1[logicalName.toLowerCase()]
},

由于某种原因,window.ENTITY_SET_NAMES 对象为空,因此发生错误(空引用)

我已经尝试将我的 Web 资源嵌入到 CRM 页面中,并且代码工作正常。问题似乎是通过 Xrm.Navigation.openWebResource

启动网络资源时

是否有人尝试在使用 Xrm.Navigation.openWebResource 打开的网络资源的上下文中使用 Xrm.WebApi?或者有人知道检索数据是否需要额外的步骤吗?


更新

ENTITY_SET_NAMESmain.aspx 中初始化。 我尝试将我的自定义 Web 资源直接嵌入到新的 Main Form 部分并且 retrieveRecord 方法有效。

只有当 运行 通过 Xrm.Navigation.openWebResource

来自新页面的 Web 资源时,这才是问题

更新 2 - 对 Aron 的回应

我尝试按照下面的建议使用 window.parent

var contactId = "8553DA63-11C9-E711-A824-000D3AE0CB84";
var promise = parent.Xrm.WebApi.retrieveRecord("contact", contactId, "$select=contactid,firstname,lastname");`

并且为了好的措施也尝试了 window.parent.top

var contactId = "8553DA63-11C9-E711-A824-000D3AE0CB84";
var promise = parent.top.Xrm.WebApi.retrieveRecord("contact", contactId, "$select=contactid,firstname,lastname");`

但两者都导致相同的错误

根据 this article,当从 Web 资源引用主表单时,我们必须引用父表单 window。虽然,它只引用 Xrm.Page 和 Xrm.Utility,但它也应该与 Xrm.WebApi...

一起使用

An HTML web resource added to a form can’t use global objects defined by the JavaScript library loaded in the form. An HTML web resource may interact with the Xrm.Page or Xrm.Utility objects within the form by using parent.Xrm.Page or parent.Xrm.Utility, but global objects defined by form scripts won’t be accessible using the parent.

请尝试parent.Xrm.WebApi.retrieveRecord("contact", contactId, "$select=contactid,firstname,lastname");

This article 也演示了 parent.Xrm.WebApi

我的blog:)


为了让这个工作正常,我实施了一个 hacky 解决方法。

我一直在调试 Xrm.WebApi 方法,它在尝试获取 entityname 并将其解析为 setname(复数)。它通过比较传递给 retrieveRecord 方法的值并将其与全局变量 ENTITY_SET_NAMES

进行比较来实现这一点

In my example, it is trying to resolve contact to contacts

不幸的是这个变量不存在,Xrm.WebApi 抛出一个错误

我的解决方法是检查此变量,如果 存在,则创建它! ENTITY_SET_NAMES 是一个 JSON 可解析字符串,其中包含每个实体的逻辑名称和集合名称。

window["ENTITY_SET_NAMES"] = window["ENTITY_SET_NAMES"] || JSON.stringify({
  "account" : "accounts",
  "contact" : "contacts"
});

在对 Xrm.WebApi 方法的任何调用似乎起作用之前执行此行,我现在得到了结果

这是完整的片段:

window["ENTITY_SET_NAMES"] = window["ENTITY_SET_NAMES"] || JSON.stringify({
  "account" : "accounts",
  "contact" : "contacts"
});

var contactId = "8553DA63-11C9-E711-A824-000D3AE0CB84";
Xrm.WebApi.retrieveRecord(
  "contact", 
  contactId, 
  "$select=contactid,firstname,lastname"
).then(
  function success(result) {
    console.log(result.firstname);
    // perform operations on record retrieval
  },
  function (error) {
    console.log(error.message);
    // handle error conditions
  }
);

听起来像是 ClientGlobalContext.js.aspx 中的产品错误,因为这应该为您提供完整的工作环境。

在这种情况下,您可能可以使用 window.opener.Xrm,因为 对于 window.opener.Xrm.Page.getAttribute 它也应该适用于 Xrm.WebApi

您可以像这样尝试从 opener window 访问变量:

window["ENTITY_SET_NAMES"] = window["ENTITY_SET_NAMES"] || window.opener.top.ENTITY_SET_NAMES;

如果您要使用绑定操作和函数,您还需要添加一个类似的变量来将实体映射到它们的主要 ID 字段。

window["ENTITY_PRIMARY_KEYS"] = ['{"account":"accountid", "contact":"contactid"}'];