如何将Client实体字段传递给虚拟实体retrieveMultiple插件?
解决方法:将Client实体字段传递给虚拟实体RetrieveMultiple插件
方案一:通过修改子网格FetchXML传递参数(推荐)
步骤1:编写Client表单的JavaScript代码
在Client表单的OnLoad事件中添加脚本,获取当前记录的ExternalId并修改子网格的FetchXML:
function onClientFormLoad(executionContext) { var formContext = executionContext.getFormContext(); var externalId = formContext.getAttribute("externalid").getValue(); if (!externalId) return; // 替换为你的子网格名称 var subgridControl = formContext.getControl("VirtualEntitySubgrid"); if (!subgridControl) return; var view = subgridControl.getView(); var fetchXml = view.fetchXml; // 解析FetchXML并添加自定义参数载体 var parser = new DOMParser(); var xmlDoc = parser.parseFromString(fetchXml, "text/xml"); var conditionNode = xmlDoc.createElement("condition"); conditionNode.setAttribute("attribute", "client_externalid_param"); conditionNode.setAttribute("operator", "eq"); conditionNode.setAttribute("value", externalId); var entityNode = xmlDoc.getElementsByTagName("entity")[0]; var filterNode = entityNode.getElementsByTagName("filter")[0]; if (!filterNode) { filterNode = xmlDoc.createElement("filter"); filterNode.setAttribute("type", "and"); entityNode.appendChild(filterNode); } filterNode.appendChild(conditionNode); var newFetchXml = new XMLSerializer().serializeToString(xmlDoc); view.fetchXml = newFetchXml; subgridControl.setView(view); subgridControl.refresh(); }
步骤2:在RetrieveMultiple插件中提取参数
在虚拟实体的RetrieveMultiple插件里,解析FetchXML拿到传递的ExternalId:
public void Execute(IServiceProvider serviceProvider) { var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); string externalId = null; if (context.InputParameters.TryGetValue("Query", out var queryObj)) { if (queryObj is FetchExpression fetchExpr) { var xmlDoc = new XmlDocument(); xmlDoc.LoadXml(fetchExpr.Query); var conditionNode = xmlDoc.SelectSingleNode("//condition[@attribute='client_externalid_param']"); externalId = conditionNode?.Attributes["value"]?.Value; } else if (queryObj is QueryExpression queryExpr) { var condition = queryExpr.Criteria.Conditions.FirstOrDefault(c => c.AttributeName == "client_externalid_param"); externalId = condition?.Values[0]?.ToString(); } } // 拿到externalId后,传入外部Web服务做筛选 if (!string.IsNullOrEmpty(externalId)) { // 你的业务逻辑代码 } // 原有虚拟实体数据获取逻辑... }
方案二:通过拦截Web API请求传递参数
步骤1:表单JavaScript拦截请求
在Client表单OnLoad事件中注册请求拦截器,给虚拟实体的RetrieveMultiple请求添加自定义参数:
function onClientFormLoad(executionContext) { var formContext = executionContext.getFormContext(); var externalId = formContext.getAttribute("externalid").getValue(); if (!externalId) return; Xrm.WebApi.addOnPreProcessRequest(function (requestContext) { var request = requestContext.getRequest(); // 替换为你的虚拟实体逻辑名称 if (request.method === "GET" && request.url.includes("your_virtual_entity_logicalname")) { request.url += (request.url.includes("?") ? "&" : "?") + "clientexternalid=" + encodeURIComponent(externalId); } }); formContext.getControl("VirtualEntitySubgrid").refresh(); }
步骤2:插件中提取URL参数
在RetrieveMultiple插件里,从请求QueryString中提取参数:
public void Execute(IServiceProvider serviceProvider) { var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); var externalId = string.Empty; if (context.SharedVariables.Contains("HttpRequest")) { var queryString = ((HttpRequestMessage)context.SharedVariables["HttpRequest"]).RequestUri.Query; var param = queryString.Split('&').FirstOrDefault(q => q.StartsWith("clientexternalid=")); if (param != null) { externalId = param.Split('=')[1].Trim(); } } if (!string.IsNullOrEmpty(externalId)) { // 使用externalId过滤外部数据源 } // 原有逻辑... }
注意事项
- 替换代码中的子网格名称、虚拟实体逻辑名称、字段逻辑名称为实际项目中的对应名称。
- 方案一中的
client_externalid_param是虚拟属性名,无需在虚拟实体中实际创建,只要保证JS和插件中名称一致即可。 - 测试时确保Client记录的
ExternalId不为空,避免传递无效参数。
内容的提问来源于stack exchange,提问作者Rakesh
相关产品推荐
相关产品推荐

