Link to home
Start Free TrialLog in
Avatar of forsters
forstersFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Query all Users from AD using asp.net c#

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

Avatar of gavsmith
gavsmith
Flag of United Kingdom of Great Britain and Northern Ireland image

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
Avatar of forsters

ASKER

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
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
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

It might be getting error because it's a null value!

try:

myRow[1] = r.Properties.[propName].Value == null ? "" :  r.Properties[propName].Value.ToString();
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!
ASKER CERTIFIED SOLUTION
Avatar of gavsmith
gavsmith
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
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

Oh yes that's much faster, brilliant thanks.
I will post my next question right now
here's the next question:

https://www.experts-exchange.com/questions/27871691/Get-User-Contact-Details-from-AD-using-asp-net-c.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