Populating a DDL with users from Active Directory

J

Jim in Arizona

My goal, somehow, is to populate a dropdownlist with all the user names
in active directory. I don't even know where to begin, really.

I added a reference to System.DirectoryServices so I could use the
System.DirectoryServices.ActiveDirectory namespace. I don't even know if
this is the right way to go as I can't seem to find anything in that
namespace that would help me query active directory for names.

I can't use an LDAP query because lDAP isn't working on our network for
some reason (never has. i posted a note asking help for this on the
win2000.general newsgroup but no one replied).

So, even if I could use the framework to access active directory to get
a list of all the users, what about security? I don't think the aspnet
account on the web server has access to the domain's directory. How
would I go about specifying an account that could be used to access the
directory (if its necessary to do so)?

All this would need to be done in VB as I don't know C#. Oh, and I'm
using VS 2005 and .NET 2.0.

Thanks!
Jim
 
M

Marc Scheuner

My goal, somehow, is to populate a dropdownlist with all the user names
in active directory. I don't even know where to begin, really.

OK, the very FIRST question I would ask myself is : REALLY ?? Do you
really need this, and second, if yes - how many users will you be
displaying?? If you have a dozen or two - okay, no problem.

If you have more than 50 or so - forget it - won't work. Having huge
long lists of user name is just totally against all usability.
I added a reference to System.DirectoryServices so I could use the
System.DirectoryServices.ActiveDirectory namespace. I don't even know if
this is the right way to go as I can't seem to find anything in that
namespace that would help me query active directory for names.

Sure, you're on the right track. Next thing you need to do is this:
since you have a domain with any number of potential organizational
units (OU's) inside it structuring your organization, you will need to
do a domain-wide search for users (if you really want that).

Again: an alternative might be to do a two-stage search. First present
the user with a list of all OU's in your domain (usually a couple or a
few dozen), e.g. "Finance", "R&D" and so forth. Once the user has
picked the OU he wants to see, then search the users inside that
(usually a MUCH smaller number than ALL the domain users) and shows
just those in a second dropdown.
I can't use an LDAP query because lDAP isn't working on our network for
some reason (never has. i posted a note asking help for this on the
win2000.general newsgroup but no one replied).

Well, if you can't use LDAP, you're totally out of luck. Active
Directory and all the System.DirectoryServices stuff is based on LDAP.
No LDAP, no go........


So, once you've decided what to do and LDAP is working, here's how you
can do a domain-wide search - if you really want to do it in the end.

First you need to know what your domain is - either ask your domain
admin, or you can peek it like so (sorry, I'm fluent in C# only, so
you'll have to do the translations to VB.NET yourself or use one of
the C#-to-VB.NET translators out there on the 'net):

// bind to the LDAP root
DirectoryEntry root = new DirectoryEntry("LDAP://RootDSE");

// grab the defaultNamingContext
string myDomain = root.Properties["defaultNamingContext"].Value;

Next, once you have your domain name, you need to set up a domain
searcher on the domain level, and search for all users inside it:

DirectoryEntry domain = new DirectoryEntry("LDAP://" + myDomain);

DirectorySearcher dsUsers = new DirectorySearcher(domain);

// set up the searcher properties - search users, and return
// just their distinguishedName, givenName (first name), and
// sn (surname = family name)

dsUsers.Filter = "(&(objectCategory=person)(objectClass=user))";

dsUsers.PropertiesToLoad.Add("distinguishedName");
dsUsers.PropertiesToLoad.Add("givenName");
dsUsers.PropertiesToLoad.Add("sn");

Now let the searcher do its magic and find all users - you will get a
"SearchResult" object back, in which you can access all the properties
you've specified in the "PropertiesToLoad" collection:

List<string> allDomainUsers = new List<string>();

foreach(SearchResult result in dsUsers.FindAll() )
{
// grab the properties and store them somewhere, e.g. in a
// List<string> or something like that, which can then be
// bound to a combobox
string firstName = result.Properties["givenName"][0].ToString();
string lastName = result.Properties["sn"][0].ToString();

allDomainUsers.Add(firstName + " " + lastName);
}

Hope this helps you get started a bit.

If you have more questions, you can go to the MSDN
System.DirectoryServices portal here:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sds/sds/portal.asp

There are LOTS of really good examples there, in both C# and VB.NET.

Or buy the excellent book by my fellow MVP's Joe Kaplan and Ryan Dunn
- really excellent stuff about Active Directory programming!

The .NET Developer's Guide to Directory Services Programming
(Microsoft Net Development Series)
http://www.amazon.com/gp/product/0321350170/

Or post here again, of course - better yet - post in the
microsoft.public.adsi.general group, that's the hard-core Active
Directory programming group.

Marc
 
J

Jim in Arizona

Marc said:
My goal, somehow, is to populate a dropdownlist with all the user names
in active directory. I don't even know where to begin, really.

OK, the very FIRST question I would ask myself is : REALLY ?? Do you
really need this, and second, if yes - how many users will you be
displaying?? If you have a dozen or two - okay, no problem.

If you have more than 50 or so - forget it - won't work. Having huge
long lists of user name is just totally against all usability.
I added a reference to System.DirectoryServices so I could use the
System.DirectoryServices.ActiveDirectory namespace. I don't even know if
this is the right way to go as I can't seem to find anything in that
namespace that would help me query active directory for names.

Sure, you're on the right track. Next thing you need to do is this:
since you have a domain with any number of potential organizational
units (OU's) inside it structuring your organization, you will need to
do a domain-wide search for users (if you really want that).

Again: an alternative might be to do a two-stage search. First present
the user with a list of all OU's in your domain (usually a couple or a
few dozen), e.g. "Finance", "R&D" and so forth. Once the user has
picked the OU he wants to see, then search the users inside that
(usually a MUCH smaller number than ALL the domain users) and shows
just those in a second dropdown.
I can't use an LDAP query because lDAP isn't working on our network for
some reason (never has. i posted a note asking help for this on the
win2000.general newsgroup but no one replied).

Well, if you can't use LDAP, you're totally out of luck. Active
Directory and all the System.DirectoryServices stuff is based on LDAP.
No LDAP, no go........


So, once you've decided what to do and LDAP is working, here's how you
can do a domain-wide search - if you really want to do it in the end.

First you need to know what your domain is - either ask your domain
admin, or you can peek it like so (sorry, I'm fluent in C# only, so
you'll have to do the translations to VB.NET yourself or use one of
the C#-to-VB.NET translators out there on the 'net):

// bind to the LDAP root
DirectoryEntry root = new DirectoryEntry("LDAP://RootDSE");

// grab the defaultNamingContext
string myDomain = root.Properties["defaultNamingContext"].Value;

Next, once you have your domain name, you need to set up a domain
searcher on the domain level, and search for all users inside it:

DirectoryEntry domain = new DirectoryEntry("LDAP://" + myDomain);

DirectorySearcher dsUsers = new DirectorySearcher(domain);

// set up the searcher properties - search users, and return
// just their distinguishedName, givenName (first name), and
// sn (surname = family name)

dsUsers.Filter = "(&(objectCategory=person)(objectClass=user))";

dsUsers.PropertiesToLoad.Add("distinguishedName");
dsUsers.PropertiesToLoad.Add("givenName");
dsUsers.PropertiesToLoad.Add("sn");

Now let the searcher do its magic and find all users - you will get a
"SearchResult" object back, in which you can access all the properties
you've specified in the "PropertiesToLoad" collection:

List<string> allDomainUsers = new List<string>();

foreach(SearchResult result in dsUsers.FindAll() )
{
// grab the properties and store them somewhere, e.g. in a
// List<string> or something like that, which can then be
// bound to a combobox
string firstName = result.Properties["givenName"][0].ToString();
string lastName = result.Properties["sn"][0].ToString();

allDomainUsers.Add(firstName + " " + lastName);
}

Hope this helps you get started a bit.

If you have more questions, you can go to the MSDN
System.DirectoryServices portal here:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sds/sds/portal.asp

There are LOTS of really good examples there, in both C# and VB.NET.

Or buy the excellent book by my fellow MVP's Joe Kaplan and Ryan Dunn
- really excellent stuff about Active Directory programming!

The .NET Developer's Guide to Directory Services Programming
(Microsoft Net Development Series)
http://www.amazon.com/gp/product/0321350170/

Or post here again, of course - better yet - post in the
microsoft.public.adsi.general group, that's the hard-core Active
Directory programming group.

Marc

Very, very informative, Marc. Thanks.

I will probably be able to translate your C# code to vb without too much
trouble. It's all similar in a way.

I helped build the domain here so I'm really familiar with the
structure. We have probably around 250 user accounts so, yea, it's way
above your recommendation of just a few dozen.

The whole purpose of this is, well, as silly as it may seem (not my deal
but asked to be done by me), is this:

The employee satisfaction workgroup has come up with this 'rock' called
the 'you rock award'. The ESQ committe wants a page on our internal
website that shows a list of all those who have had 'the rock'. In order
to take the work out of me or anyone else in the IS staff, we (my
co-worker and I) figured it would be a good idea if the individual
employee controlled what happens. After a week, the employee could hand
the rock off to someone else who the employee thinks deserves it. They
would then go to the internal website and they could use a drop down
list which would show all employess in the agency to pick the employee
the just gave the award to then click a submit button. Once they did
that, the new person would be added as the newest record in a database.
The newest record in the database would be added the top of a list on a
page which shows they got the award and when. The person in the list
right below their name is the person who gave them the award. Now, with
the new person the last record, the home page on the internal website
would now show the same drop down list of AD users so when the newly
seclected employee decided to pass on the award, they could now repeat
the same process. The person that gave them the award would, once they
gave the award away, would no longer have access to this drop down list.

The reason I wanted a drop down list is because it would be easier to
control the real AD username when using the system. The person giving
the award out may not know the actual AD username (ex. Jon Smith being
jsmith or jonsmi) and without that, it wouldn't be possible to control
the drop down list being displayed on the home page for just the person
show currently holds the award.

Feww. I hope all that made sense.

The employees wouldn't really know how to traverse the OUs in AD. No one
ever queries it directly in any way, not even through My Network Places.
The only time anyone sees a list of names is when they look through
the exchange address book in outlook.

Anyway. I think I have enough info to go forward, one way or another.

OH, and I think LDAP will work. I was trying to use WAB.exe to look at
the directory, which wouldn't work, as I was told in the active
directory news group.

Once again, Thanks Marc.
 
Joined
Jul 2, 2007
Messages
1
Reaction score
0
Try this

I've been wanting to do something similar. This should do the job for you. I am working on caching this so it will render quicker. You might want to tweak the filter, I filter using mail (ie, user must have email address) as I am using my drop down list control to send emails.

ASPX Page
Code:
<asp:DropDownList ID="DropDownList1" runat="server"></asp:DropDownList>

Code Behind File
Code:
DirectoryEntry entry = new DirectoryEntry("LDAP://YOURDOMAIN/YOURCONTEXT", "YOURUSERNAME", "YOURPASSWORD", AuthenticationTypes.Secure);
        DirectorySearcher search = new DirectorySearcher(entry);
        search.Filter = "(&(mail=*.com)(objectClass=user))";
        search.PropertiesToLoad.Add("sAMAccountName");
        search.PropertiesToLoad.Add("givenName");
        search.PropertiesToLoad.Add("sn");
        search.PropertiesToLoad.Add("department");
        search.PropertiesToLoad.Add("mail");

        // Declare objects
        //
        DataTable dt = new DataTable();
        DataRow dr;
        int RowCount = 0;

        // Add required columns to grid
        dt.Columns.Add(new DataColumn("Username", Type.GetType("System.String")));
        dt.Columns.Add(new DataColumn("FirstName", Type.GetType("System.String")));
        dt.Columns.Add(new DataColumn("LastName", Type.GetType("System.String")));
        dt.Columns.Add(new DataColumn("Department", Type.GetType("System.String")));
        dt.Columns.Add(new DataColumn("Email", Type.GetType("System.String")));

        // Loop add rows
        foreach (SearchResult result in search.FindAll())
        {
            RowCount++; // datarow number
            try
            {
                dr = dt.NewRow();

                DirectoryEntry dirEntry = result.GetDirectoryEntry();
                dr[0] = dirEntry.Properties["sAMAccountName"].Value.ToString();
                dr[1] = dirEntry.Properties["givenName"].Value.ToString();
                dr[2] = dirEntry.Properties["sn"].Value.ToString();
                dr[3] = dirEntry.Properties["department"].Value.ToString();
                dr[4] = dirEntry.Properties["mail"].Value.ToString();

                dt.Rows.Add(dr);
            }
            catch
            {
            }
        }
        DropDownList1.DataSource = dt;
        DropDownList1.DataTextField = "Username";
        DropDownList1.DataValueField = "Username";
        DropDownList1.DataBind();
 
Last edited:
Joined
Dec 3, 2008
Messages
1
Reaction score
0
selected item & value

cgerke,

I used your codes but when I tried to get the selected item & value, I always got the default value of the first entry. Seems like when I click on submit button, it causes a postback & it gets the first item & value from the list (which is not the item I selected).

How can I fix this?

Thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top