跨服务器获取Dynamics CRM账户字段遇DisplayName空值异常
解决Dynamics 365 RetrieveEntityRequest获取字段DisplayName为空的问题
根据你描述的场景,这个问题大概率和元数据发布状态、本地化标签的获取逻辑以及RetrieveAsIfPublished参数的设置有关。下面是几个针对性的解决方案,你可以逐一尝试:
1. 修改RetrieveAsIfPublished参数为true
你当前请求里设置了RetrieveAsIfPublished = false,这会获取系统中已发布的元数据,但如果自定义字段刚添加到表单且发布过程存在延迟/异常,可能导致元数据不同步。改成true后,会获取最新的(包括未完全发布的)元数据,能避免这类同步问题:
RetrieveEntityRequest request = new RetrieveEntityRequest() { EntityFilters = EntityFilters.Attributes, RetrieveAsIfPublished = true, // 这里改为true LogicalName = "account" };
2. 替换UserLocalizedLabel为指定语言的标签获取逻辑
UserLocalizedLabel依赖当前用户的语言设置,如果组织默认语言和用户语言不匹配,或者自定义字段未在该语言下配置标签,就会返回null。建议直接获取组织默认语言的标签(比如中文用2052,英文用1033),或者遍历所有标签取第一个非空值作为兜底:
// 示例:获取组织默认语言(假设是中文2052)的标签 var defaultLanguageCode = 2052; // 替换成你的组织实际默认语言码 var localizedLabel = attribute.DisplayName.LocalizedLabels .FirstOrDefault(l => l.LanguageCode == defaultLanguageCode) ?? attribute.DisplayName.LocalizedLabels.FirstOrDefault(); // fallback到第一个存在的标签 ef.DisplayName = localizedLabel?.Label ?? attribute.LogicalName; // 最后用逻辑名兜底,避免空值
3. 强制发布所有相关元数据
有时候移除自定义字段再发布能恢复,说明之前的发布操作可能没有完全生效。可以用代码强制发布账户实体及相关表单的元数据:
// 发布所有元数据(适合快速排查) PublishAllXmlRequest publishRequest = new PublishAllXmlRequest(); service.Execute(publishRequest); // 或者仅发布账户实体(更精准) PublishXmlRequest publishEntityRequest = new PublishXmlRequest { ParameterXml = "<importexportxml><entities><entity>account</entity></entities></importexportxml>" }; service.Execute(publishEntityRequest);
4. 检查自定义字段的标签配置
登录Dynamics 365后台,进入自定义字段的编辑页面,确认该字段在所有需要的语言下都配置了显示名称,至少要保证组织默认语言下有值。如果某语言的标签为空,当用户用该语言访问时,UserLocalizedLabel就会返回null。
5. 优化代码中的空值判断逻辑
原代码里的判断条件有重复,同时可以给DisplayName增加兜底逻辑,避免因为标签为空导致整个字段被过滤掉:
foreach (AttributeMetadata attribute in currentEntity.Attributes) { // 简化空值判断逻辑 if (attribute.IsValidForRead.HasValue && attribute.IsValidForRead.Value && !string.IsNullOrEmpty(attribute.LogicalName) && _allowedFieldTypes.Contains(attribute.AttributeType.ToString().ToLower())) { EntityField ef = new EntityField(); ef.AttributeType = attribute.AttributeType.ToString() ?? string.Empty; ef.IsCustomField = attribute.IsCustomAttribute ?? false; ef.IsAllowUpdate = attribute.IsValidForUpdate ?? false; ef.LogicalName = attribute.LogicalName; // 处理DisplayName,多层兜底 var displayLabel = attribute.DisplayName.UserLocalizedLabel?.Label; if (string.IsNullOrEmpty(displayLabel)) { var defaultLabel = attribute.DisplayName.LocalizedLabels.FirstOrDefault()?.Label; displayLabel = defaultLabel ?? attribute.LogicalName; } ef.DisplayName = displayLabel; // 原有选项集处理逻辑保持不变 if (attribute.AttributeType.ToString().ToLower() == "picklist") { PicklistAttributeMetadata pm = (PicklistAttributeMetadata)attribute; foreach (OptionMetadata x in pm.OptionSet.Options) { ef.Items.Add(x.Label.UserLocalizedLabel?.Label ?? x.Value.ToString()); } } else if (attribute.AttributeTypeName.Value == "MultiSelectPicklistType") { MultiSelectPicklistAttributeMetadata pm = (MultiSelectPicklistAttributeMetadata)attribute; foreach (OptionMetadata x in pm.OptionSet.Options) { ef.Items.Add(x.Label.UserLocalizedLabel?.Label ?? x.Value.ToString()); } } if (Add) { fieldLst.Add(ef); } } }
优先尝试修改RetrieveAsIfPublished参数和优化标签获取逻辑,这两个是最常见的触发原因。
内容的提问来源于stack exchange,提问作者Virendra Yadav
相关产品推荐
相关产品推荐

