[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Query all Users from AD using asp.net c#

Posted on 2012-09-19
11
Medium Priority
?
1,220 Views
Last Modified: 2012-09-20
Hi Experts,

Been finding my way around querying AD from asp.net.

http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/Q_27868932.html

And now trying to work out how I can get information for a group of users / all users (@350)
Or if thats a really bad idea...please advise. For example if I wanted contact details for all users is there a good way to do that and bind it to a grid or list?

I cobbled together a piece of code (below) based on an example and what I had already but due to my newbie c# skills and not being 100% sure what I should be expecting to get i'm clearly making a few fundamental errors in my cobbling because I get back a list of property headings but no actual values...or thats what appears to be happening. I'd be greatful of some help to get me a bit nearer my objective.

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.DirectoryServices;
using System.Configuration;
using System.Data;

public partial class Default4 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

        ADUserProperties.DataSource = GetUsers();
        ADUserProperties.DataBind();
    }

    protected DataTable GetUsers()
    {

        DirectoryEntry de = new DirectoryEntry(ConfigurationManager.AppSettings.Get("ADPath")); // Authentication details
        de.Username = ConfigurationManager.AppSettings.Get("ADServiceAccount"); //DOMAIN\User
        de.Password = ConfigurationManager.AppSettings.Get("ADServiceAccountPassword");
        de.AuthenticationType = AuthenticationTypes.FastBind;

        DirectorySearcher searcher1 = new DirectorySearcher("(&(objectCategory=Person)(objectClass=user))");
        searcher1.SearchRoot = de;
        searcher1.SearchScope = SearchScope.Subtree;
        SearchResultCollection results1;
        results1 = searcher1.FindAll();
        if (results1 != null)
        {
            // Create a table and populate it with properties to bind to gridview
            DataTable myTable = new DataTable("ActiveDir");
            myTable.Columns.Add(new DataColumn("Key", System.Type.GetType("System.String")));
            myTable.Columns.Add(new DataColumn("Value", System.Type.GetType("System.String")));
            DataRow myRow;
            foreach (SearchResult r in results1)
            {
                foreach (Object objValue in r.Properties)
                {
                    myRow = myTable.NewRow();
                    myRow[0] = r.Properties;
                    myRow[1] = objValue.ToString();
                    myTable.Rows.Add(myRow);
                }
            }
            return myTable;
        }
        else
        {
            return null;
        }
    }
} 

Open in new window

0
Comment
Question by:forsters
  • 6
  • 5
11 Comments
 
LVL 10

Expert Comment

by:gavsmith
ID: 38416842
Hi, try:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.DirectoryServices;
using System.Configuration;
using System.Data;

public partial class Default4 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

        ADUserProperties.DataSource = GetUsers();
        ADUserProperties.DataBind();
    }

    protected DataTable GetUsers()
    {

        DirectoryEntry de = new DirectoryEntry(ConfigurationManager.AppSettings.Get("ADPath")); // Authentication details
        de.Username = ConfigurationManager.AppSettings.Get("ADServiceAccount"); //DOMAIN\User
        de.Password = ConfigurationManager.AppSettings.Get("ADServiceAccountPassword");
        de.AuthenticationType = AuthenticationTypes.FastBind;

        DirectorySearcher searcher1 = new DirectorySearcher("(&(objectCategory=Person)(objectClass=user))");
        searcher1.SearchRoot = de;
        searcher1.SearchScope = SearchScope.Subtree;
        SearchResultCollection results1;
        results1 = searcher1.FindAll();
        if (results1 != null)
        {
            // Create a table and populate it with properties to bind to gridview
            DataTable myTable = new DataTable("ActiveDir");
            myTable.Columns.Add(new DataColumn("Key", System.Type.GetType("System.String")));
            myTable.Columns.Add(new DataColumn("Value", System.Type.GetType("System.String")));
            DataRow myRow;
            foreach (SearchResult r in results1)
            {
                foreach (Object objValue in r.Properties)
                {
                    myRow = myTable.NewRow();
                    myRow[0] = objValue.Name;
                    myRow[1] = objValue.Value.ToString();
                    myTable.Rows.Add(myRow);
                }
            }
            return myTable;
        }
        else
        {
            return null;
        }
    }
} 

Open in new window


You are currently setting the rows values to collection classes which is why it's displaying wrong.

Hope that helps
Gav
0
 

Author Comment

by:forsters
ID: 38416875
Hi Gav,

Thank you, that makes sense, however I'm getting an error on the .Name and .Value in :

foreach (Object objValue in r.Properties)
                {
                    myRow = myTable.NewRow();
                    myRow[0] = objValue.Name;
                    myRow[1] = objValue.Value.ToString();
                    myTable.Rows.Add(myRow);
                }

Open in new window


In both cases i'm told "'object' does not contain a definition for 'Name' or 'Value' etc", the only options that seem to be available for objValue are: Equals, Get Hash Code, Get Type, ToString.

I'm afraid i'm a bit lost on this
0
 
LVL 10

Expert Comment

by:gavsmith
ID: 38416903
Oh yes, sorry didn't think of that, try this instead:

foreach (SearchResult r in results1)
{
  foreach (string propName in r.Properties.PropertyNames)
                {
                    myRow = myTable.NewRow();
                    myRow[0] = propName;
                    myRow[1] = r.Properties[propName].Value.ToString();
                    myTable.Rows.Add(myRow);
                }
}

Open in new window


Sorry I can not test this (quickly), please let me know the result
0
Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

 

Author Comment

by:forsters
ID: 38416914
Thank you, that has got rid of the error on the .Name, but it still objects to .Value in:

myRow[1] = r.Properties[propName].Value.ToString();

Open in new window

0
 
LVL 10

Expert Comment

by:gavsmith
ID: 38416934
It might be getting error because it's a null value!

try:

myRow[1] = r.Properties.[propName].Value == null ? "" :  r.Properties[propName].Value.ToString();
0
 

Author Comment

by:forsters
ID: 38416992
I get the error before I even run the code if that makes sense - the squiggly red underline:

System.DirectoryServices.ResultPropertyValueCollection does not contain a definition for 'Value' etc..

In the last code snip you gave I get a tiny red squiggle under the opening square bracket of [propName] (error says identifyer expected) and then it underlines the second occurrence of Value with the error provided.

I can see what we're trying to do but this is where my c# is too newbie to experiment with anything more than pure luck!
0
 
LVL 10

Accepted Solution

by:
gavsmith earned 2000 total points
ID: 38417048
Sorry I'm not thinking straight lately let me try again...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.DirectoryServices;
using System.Configuration;
using System.Data;

public partial class Default4 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

        ADUserProperties.DataSource = GetUsers();
        ADUserProperties.DataBind();
    }

    protected DataTable GetUsers()
    {

        DirectoryEntry de = new DirectoryEntry(ConfigurationManager.AppSettings.Get("ADPath")); // Authentication details
        de.Username = ConfigurationManager.AppSettings.Get("ADServiceAccount"); //DOMAIN\User
        de.Password = ConfigurationManager.AppSettings.Get("ADServiceAccountPassword");
        de.AuthenticationType = AuthenticationTypes.FastBind;

        DirectorySearcher searcher1 = new DirectorySearcher("(&(objectCategory=Person)(objectClass=user))");
        searcher1.SearchRoot = de;
        searcher1.SearchScope = SearchScope.Subtree;
        SearchResultCollection results1;
        results1 = searcher1.FindAll();
        if (results1 != null)
        {
            // Create a table and populate it with properties to bind to gridview
            DataTable myTable = new DataTable("ActiveDir");
            myTable.Columns.Add(new DataColumn("Key", System.Type.GetType("System.String")));
            myTable.Columns.Add(new DataColumn("Value", System.Type.GetType("System.String")));
            DataRow myRow;
            foreach (SearchResult r in results1)
            {
                 DirectoryEntry de = r.GetDirectoryEntry();
                 foreach (string propName in de.Properties.PropertyNames)
                 {
                    myRow = myTable.NewRow();
                    myRow[0] = propName;
                    myRow[1] = de.Properties[propName].Value == null ? "" :  de.Properties[propName].Value.ToString(); 
                    myTable.Rows.Add(myRow);
                }
            }
            return myTable;
        }
        else
        {
            return null;
        }
    }
} 

Open in new window

0
 

Author Comment

by:forsters
ID: 38417072
Awesome, one minor tweak and it ran albeit taking about 30secs to load (i've got way more info than I actually need or want now) but thats another matter.

so where you had added:

 
DirectoryEntry de = r.GetDirectoryEntry();

Open in new window


I just removed 'DirectoryEntry' so my line read:

 
de = r.GetDirectoryEntry();

Open in new window


Thank you I will have a little mess about and probably be back with another question in about 30 mins

Thanks for your help.
0
 
LVL 10

Expert Comment

by:gavsmith
ID: 38417105
Glad I could help, please post on here if you create another question and I'll try to assist.

I didn't realise you had alread declared de, you may not need the DirectoryEntry here's another alternative, it may increase performance!?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.DirectoryServices;
using System.Configuration;
using System.Data;

public partial class Default4 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

        ADUserProperties.DataSource = GetUsers();
        ADUserProperties.DataBind();
    }

    protected DataTable GetUsers()
    {

        DirectoryEntry de = new DirectoryEntry(ConfigurationManager.AppSettings.Get("ADPath")); // Authentication details
        de.Username = ConfigurationManager.AppSettings.Get("ADServiceAccount"); //DOMAIN\User
        de.Password = ConfigurationManager.AppSettings.Get("ADServiceAccountPassword");
        de.AuthenticationType = AuthenticationTypes.FastBind;

        DirectorySearcher searcher1 = new DirectorySearcher("(&(objectCategory=Person)(objectClass=user))");
        searcher1.SearchRoot = de;
        searcher1.SearchScope = SearchScope.Subtree;
        SearchResultCollection results1;
        results1 = searcher1.FindAll();
        if (results1 != null)
        {
            // Create a table and populate it with properties to bind to gridview
            DataTable myTable = new DataTable("ActiveDir");
            myTable.Columns.Add(new DataColumn("Key", System.Type.GetType("System.String")));
            myTable.Columns.Add(new DataColumn("Value", System.Type.GetType("System.String")));
            DataRow myRow;
            foreach (SearchResult r in results1)
            {
                 foreach (string propName in r.Properties.PropertyNames)
                 {
                    myRow = myTable.NewRow();
                    myRow[0] = propName;
                    foreach (Object objValue in r.Properties[propName])
                        myRow[1] += objValue + " "; 
                    myTable.Rows.Add(myRow);
                }
            }
            return myTable;
        }
        else
        {
            return null;
        }
    }
} 

Open in new window

0
 

Author Comment

by:forsters
ID: 38417124
Oh yes that's much faster, brilliant thanks.
I will post my next question right now
0
 

Author Comment

by:forsters
ID: 38417180
here's the next question:

http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/Q_27871691.html

we need to give users the details that will appear on their outlook signature - in the format that they will appear so that they can approve / challenge accuracy of details...

Many TIA
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A bad practice commonly found during an account life cycle is to set its password to an initial, insecure password. The Password Reset Tool was developed to make the password reset process easier and more secure.
Hello there! As a developer I have modified and refactored the unit tests which was written by fellow developers in the past. On the course, I have gone through various misconceptions and technical challenges when it comes to implementation. I would…
This tutorial will walk an individual through the process of transferring the five major, necessary Active Directory Roles, commonly referred to as the FSMO roles to another domain controller. Log onto the new domain controller with a user account t…
This tutorial will walk an individual through the process of configuring their Windows Server 2012 domain controller to synchronize its time with a trusted, external resource. Use Google, Bing, or other preferred search engine to locate trusted NTP …
Suggested Courses

831 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question