.NET通过WebAPI用FetchXml查询Dataverse含#字符序列号问题
问题
在.NET中通过WebAPI使用FetchXml从Dynamics 365 CE(Dataverse)检索记录,因限制只能用GET请求,需在查询字符串中过滤含#等特殊字符的SerialNumber字段,但直接传入会导致XML无效。尝试过WebUtility.UrlEncode、HtmlEncode及双重编码,均无法正确检索到对应记录。当前使用的FetchXml模板如下:
<fetch> <entity name='{im_customerequipment.EntityLogicalName}'> <attribute name='{im_customerequipment.Fields.Id}' /> <attribute name='{im_customerequipment.Fields.im_SerialNo}' /> <attribute name='{im_customerequipment.Fields.im_AccountId}' /> <filter> <condition attribute='{im_customerequipment.Fields.OwningBusinessUnit}' operator='eq' value='{businessUnitId.ToString()}'/> <condition attribute='{im_customerequipment.Fields.im_SerialNo}' operator='in'> {string.Join("", serialNumbers.Skip(page * pageSize).Take(pageSize).Select(serialNumber => $"<value>{serialNumber}</value>"))} </condition> </filter> </entity>
请问如何正确转义#字符,使其在Dataverse端能被正确识别并检索到对应记录?
解决方案
针对Dataverse GET请求中FetchXml含特殊字符的转义,需遵循先XML转义,再URL编码的顺序,具体步骤如下:
对单个序列号做XML实体转义
对于#这类特殊字符,首先要转义为XML实体#,同时处理其他可能破坏XML结构的字符(如<、>、&、'、")。推荐使用System.Security.SecurityElement.Escape()方法,它会自动将所有XML特殊字符转换为对应实体。生成完整FetchXml后再做URL编码
先将转义后的序列号插入FetchXml模板生成完整XML字符串,再对整个XML做URL编码,最后拼接到GET请求的fetchXml查询参数中。
代码示例
修改生成<value>节点的逻辑,加入XML转义步骤:
// 对每个序列号先执行XML转义 var escapedSerialNumbers = serialNumbers .Skip(page * pageSize) .Take(pageSize) .Select(sn => System.Security.SecurityElement.Escape(sn)); // 生成FetchXml中的<value>节点片段 var valueNodes = string.Join("", escapedSerialNumbers.Select(sn => $"<value>{sn}</value>")); // 拼接完整的FetchXml字符串 string fetchXml = $@"<fetch> <entity name='{im_customerequipment.EntityLogicalName}'> <attribute name='{im_customerequipment.Fields.Id}' /> <attribute name='{im_customerequipment.Fields.im_SerialNo}' /> <attribute name='{im_customerequipment.Fields.im_AccountId}' /> <filter> <condition attribute='{im_customerequipment.Fields.OwningBusinessUnit}' operator='eq' value='{businessUnitId.ToString()}'/> <condition attribute='{im_customerequipment.Fields.im_SerialNo}' operator='in'> {valueNodes} </condition> </filter> </entity> </fetch>"; // 对整个FetchXml执行URL编码 string encodedFetchXml = WebUtility.UrlEncode(fetchXml); // 拼接最终的GET请求URL string requestUrl = $"https://your-org.crm.dynamics.com/api/data/v9.2/{im_customerequipment.EntityLogicalName}?fetchXml={encodedFetchXml}";
关键说明
- 禁止直接对原始序列号做URL编码后插入XML,这会导致XML解析错误(URL编码后的
#是%23,XML会将其视为普通文本,而Dataverse需要的是原始字符的XML实体表示)。 SecurityElement.Escape()会处理所有XML预定义实体,包括:&→&<→<>→>'→'"→"#→#
- 最后对整个FetchXml做URL编码,确保字符串能安全通过查询字符串传输,不会被浏览器或服务器截断。
内容的提问来源于stack exchange,提问作者Flashcap
相关产品推荐
相关产品推荐

