System.DirectoryServices.AccountManagement并返回IEnumerable的Active Directory用户

时间:2018-04-11 23:40:07

标签: c# asp.net-mvc active-directory

我试图查询Active Directory并返回一个IEnumerable但是使用Title和EmailAddress这样的属性,这些属性没有显示在做PrincipalSearcher.Findll()。如果我使用PrincipalSearcher.FindOne(),它有更多的属性(但仍然不是标题),所以我试图找出我做的不同或者如何得到我需要的信息。谷歌试图找到更多信息已经疲惫不堪,看起来像UserPrincipal.GetUnderlyingObject()可能是票,但我不明白如何将其纳入foreach循环以便将其填入列表

    public class ADUser
    {
        public string SamAccountName { get; set; }
        public string DisplayName { get; set; }
        public string Title { get; set; }

        public IEnumerable<ADUser> Get(string username)
        {
            var users = new List<ADUser>();

            var principalContext = new PrincipalContext(ContextType.Domain, "domain.com");
            var userPrincipal = new UserPrincipal(principalContext)
            {
                SamAccountName = username
            };

            var principalSearcher = new PrincipalSearcher(userPrincipal);

            foreach (var user in principalSearcher.FindAll())
            {
                users.Add(new ADUser
                {
                    SamAccountName = user.SamAccountName,
                    DisplayName = user.DisplayName,
                    //Title = user.Title //Won't work, no Title property
                });
            }

            return users;
        }
    }

这有效,但只返回.FindOne()所做的一小部分属性,但是如果我做了FindOne(),我就无法搜索部分用户名,例如&#34; jsm&#34 ;回归&#34;约翰史密斯&#34;和#34; James Smoth&#34;。

1 个答案:

答案 0 :(得分:1)

简短的回答是你可以这样做:

        foreach (var user in principalSearcher.FindAll())
        {
            var userDe = (DirectoryEntry) user.GetUnderlyingObject();
            users.Add(new ADUser
            {
                SamAccountName = user.SamAccountName,
                DisplayName = user.DisplayName,
                Title = userDe.Properties["title"]?.Value.ToString()
            });
        }

这是我再也不使用AccountManagement命名空间的部分原因了。它在后台使用DirectoryEntry并隐藏其复杂性,以便让您更轻松地完成基本操作,但您仍需要直接使用DirectoryEntry来处理某些事情。它实际上比直接使用DirectoryEntry / DirectorySearcher要慢。

以下是您如何通过DirectorySearcher执行相同操作的示例。这有点复杂,但我打赌你会发现它表现得更快:

public class ADUser
{
    public string SamAccountName { get; set; }
    public string DisplayName { get; set; }
    public string Title { get; set; }

    public IEnumerable<ADUser> Get(string username)
    {
        var users = new List<ADUser>();

        var search = new DirectorySearcher(
            new DirectoryEntry("LDAP://domain.com"),
            $"(&(objectClass=user)(objectCategory=person)(sAMAccountName={username}))",
            new [] { "sAMAccountName", "displayName", "title" } //The attributes you want to see
        ) {
            PageSize = 1000 //If you're expecting more than 1000 results, you need this otherwise you'll only get the first 1000 and it'll stop
        };

        using (var results = search.FindAll()) {
            foreach (SearchResult result in results)
            {
                users.Add(new ADUser
                {
                    SamAccountName = result.Properties.Contains("sAMAccountName") ? result.Properties["sAMAccountName"][0].ToString() : null,
                    DisplayName = result.Properties.Contains("displayName") ? result.Properties["displayName"][0].ToString() : null,
                    Title = result.Properties.Contains("title") ? result.Properties["title"][0].ToString() : null
                });
            }
        }
        return users;
    }
}