如何用C#获取Azure AD用户全部属性(含空值)并同步至其他AD
获取Azure AD用户全部属性(含空属性)的C#实现
我之前做过Azure AD到第三方AD的同步需求,正好碰到过这个“获取所有属性包括空值”的问题,这里给你分享下实操思路和代码:
核心问题分析
Graph API默认只返回用户的常用属性,而且即使你用$select=*,那些从未设置过的空属性也不会被包含在返回结果里。要拿到所有属性(包括空的),关键是:
- 先明确Azure AD User实体有哪些属性
- 显式指定所有属性进行查询,这样空属性会以
null的形式返回(或者在SDK对象中体现为默认值)
步骤1:获取User实体的所有属性名称
最可靠的方式是从Graph API的元数据中解析出User实体的全部属性,而不是手动枚举(避免遗漏新增属性)。下面是用C#解析元数据的代码:
using Microsoft.Graph; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using System.Xml.Linq; private async Task<List<string>> GetUserPropertyNamesAsync(GraphServiceClient graphClient) { // 请求Graph元数据 var metadataRequest = new HttpRequestMessage(HttpMethod.Get, "$metadata"); var metadataResponse = await graphClient.HttpProvider.SendAsync(metadataRequest); metadataResponse.EnsureSuccessStatusCode(); var metadataContent = await metadataResponse.Content.ReadAsStringAsync(); var xDoc = XDocument.Parse(metadataContent); // 定义OData命名空间 var edmxNs = "http://docs.oasis-open.org/odata/ns/edmx"; var edmNs = "http://docs.oasis-open.org/odata/ns/edm"; // 找到User实体类型 var userEntity = xDoc.Descendants(XName.Get("EntityType", edmNs)) .FirstOrDefault(e => e.Attribute("Name")?.Value == "User"); if (userEntity == null) throw new System.Exception("未找到User实体元数据"); // 提取所有属性名称 var propertyNames = userEntity.Descendants(XName.Get("Property", edmNs)) .Select(p => p.Attribute("Name")?.Value) .Where(name => !string.IsNullOrEmpty(name)) .ToList(); // 手动添加扩展属性(部分扩展属性可能不在元数据的直接属性列表中) for (int i = 1; i <= 15; i++) { var extAttrName = $"onPremisesExtensionAttributes{i}"; if (!propertyNames.Contains(extAttrName)) propertyNames.Add(extAttrName); } return propertyNames; }
步骤2:批量获取所有用户(含全属性)
拿到属性列表后,构造$select参数,分页获取所有用户(Graph API单次最多返回999条):
public async Task<List<User>> GetAllUsersWithFullPropertiesAsync(GraphServiceClient graphClient) { var allProperties = await GetUserPropertyNamesAsync(graphClient); var selectClause = string.Join(",", allProperties); var allUsers = new List<User>(); // 首次请求,每页999条(Graph API最大页容量) var currentPage = await graphClient.Users .Request() .Select(selectClause) .Top(999) .GetAsync(); allUsers.AddRange(currentPage.CurrentPage); // 处理分页 while (currentPage.NextPageRequest != null) { currentPage = await currentPage.NextPageRequest.GetAsync(); allUsers.AddRange(currentPage.CurrentPage); } return allUsers; }
步骤3:处理空属性同步
当你拿到User对象后,那些从未设置过的属性会以null(引用类型)或默认值(值类型)的形式存在。同步到目标AD时,直接将这些值映射过去即可:
- 比如
user.MobilePhone如果为null,就给目标AD对应的字段设置为空字符串 - 注意部分属性是只读的(如
createdDateTime),或者需要特殊权限才能获取(如passwordProfile),同步时要跳过或做针对性处理
权限说明
确保你的Azure AD应用已授予Directory.Read.All应用权限(不是委托权限),并且已完成管理员同意,否则会出现权限不足的错误。
内容的提问来源于stack exchange,提问作者James Barnes
相关产品推荐
相关产品推荐

