• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 799
  • Last Modified:

get user groups from AD

I need the get a list of groups that a certain user belongs to in Active Directory using asp.net 2.0 with c#.

Below is failed code:
        public static string GetUserGroupMembership(string strUser)
        {
            StringCollection groups = new StringCollection();
            string strConn;
            //active directory connection string
            strConn = (ConfigurationManager.ConnectionStrings["ADConnectionString"]).ToString();

            try
            {
                DirectoryEntry obEntry = new DirectoryEntry(strConn);
                DirectorySearcher srch = new DirectorySearcher(obEntry, "(sAMAccountName=" + strUser + ")");
                SearchResult res = srch.FindOne();
                if (null != res)
                {
                    DirectoryEntry obUser = new DirectoryEntry(res.Path);
                    // Invoke Groups method.
                    object obGroups = obUser.Invoke("Groups");
                    foreach (object ob in (IEnumerable)obGroups)
                    {
                        // Create object for each group.
                        DirectoryEntry obGpEntry = new DirectoryEntry(ob);
                        groups.Add(obGpEntry.Name);
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.Write(ex.Message);
            }
            return groups.ToString();
        }

My error: Using the generic type 'System.Collections.Generic.IEnumerable<T>' requires '1' type arguments
0
fwsteal
Asked:
fwsteal
  • 19
  • 17
1 Solution
 
Bob LearnedCommented:
Do you have this
    using System.Collections;

or, this?
   using System.Collections.Generic;

Bob
0
 
fwstealAuthor Commented:
here are my directives.

using System;
using System.Data;
using System.Configuration;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Diagnostics;
using System.Collections.Specialized;

0
 
fwstealAuthor Commented:
i did this:

        public static string GetUserGroupMembership(string strUser)
        {
            StringCollection groups = new StringCollection();
            string strConn;
            //active directory connection string
            strConn = (ConfigurationManager.ConnectionStrings["ADConnectionString"]).ToString();

            try
            {
                DirectoryEntry obEntry = new DirectoryEntry(strConn);
                DirectorySearcher srch = new DirectorySearcher(obEntry, "(sAMAccountName=" + strUser + ")");
                SearchResult res = srch.FindOne();
                if (null != res)
                {
                    DirectoryEntry obUser = new DirectoryEntry(res.Path);
                    // Invoke Groups method.
                    object obGroups = obUser.Invoke("Groups");
                    foreach (object ob in (System.Collections.IEnumerable)obGroups)
                    //Using the generic type 'System.Collections.Generic.IEnumerable<T>' requires '1' type arguments
                    {
                        // Create object for each group.
                        DirectoryEntry obGpEntry = new DirectoryEntry(ob);
                        groups.Add(obGpEntry.Name);
                    }
                }
                return groups.ToString(); //System.Collections.Specialized.StringCollection
            }
            catch (Exception ex)
            {
                Trace.Write(ex.Message);
                return ex.ToString();
            }
        }

and get this as the returned value: System.Collections.Specialized.StringCollection

not what I was hoping for; how to I get my groups?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Bob LearnedCommented:
Try this:

1) Dimension list:

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

2) Add to list:

   groups.Add(obGpEntry.Name);

3) Return the list:

   return groups;

4) Change the return type for the function:

public static List<string> GetUserGroupMembership(string strUser)

5) Remove the using System.Collections.Specialized

Bob
0
 
fwstealAuthor Commented:
I noticed in debug that:

DirectoryEntry obUser = new DirectoryEntry(res.Path);
  Path = "LDAP://domaindev.net/CN=fname lname,OU=Developers,DC=DomainDev,DC=net"


Using, http://adsi.mvps.org/adsi/CSharp/beavertail.html  has helped by seeing the OUs. If the user is not in a group but in an OU, how do I get the OUs that the user is in?


I'd still like to get the groups as well as get the OUs.
0
 
fwstealAuthor Commented:
Bob, Okay you lost me on 1 - 3. How do I write that block?
0
 
Bob LearnedCommented:
Coding in the comment block:

public static List<string> GetUserGroupMembership(string strUser)
        {
            List<string> groups = new List<string>();
            //active directory connection string
            string strConn = ConfigurationManager.ConnectionStrings["ADConnectionString"].ConnectionString;

            try
            {
                DirectoryEntry obEntry = new DirectoryEntry(strConn);
                DirectorySearcher srch = new DirectorySearcher(obEntry, "(sAMAccountName=" + strUser + ")");
                SearchResult res = srch.FindOne();
                if (null != res)
                {
                    DirectoryEntry obUser = new DirectoryEntry(res.Path);
                    // Invoke Groups method.
                    object obGroups = obUser.Invoke("Groups");
                    foreach (object ob in (IEnumerable)obGroups)
                    {
                        // Create object for each group.
                        DirectoryEntry obGpEntry = new DirectoryEntry(ob);
                        groups.Add(obGpEntry.Name);
                    }
                }
                return groups;
            }
            catch (Exception ex)
            {
                Trace.Write(ex.Message);
                return ex.ToString();
            }
        }

Bob
0
 
fwstealAuthor Commented:
Bob,

I got the following errors:

My errors:
Error 1 Cannot implicitly convert type 'System.Collections.Generic.List<string>' to 'string'      Default.aspx.cs
Error 2      Using the generic type 'System.Collections.Generic.IEnumerable<T>' requires '1' type arguments      \UserDetails.cs
Error 3      Cannot implicitly convert type 'string' to 'System.Collections.Generic.List<string>'      \UserDetails.cs
----------------
Errors on page
Default.aspx.cs
1. lblUserGroups.Text = UserDetails.GetUserGroupMembership(Server.HtmlEncode(User.Identity.Name));

UserDetails.cs
2. foreach (object ob in (IEnumerable)obGroups)
3. return ex.ToString();
-----------
Page Code:

1. default.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Security.Principal;
using System.Text;

namespace AD
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
          lblUserGroups.Text = UserDetails.GetUserGroupMembership(Server.HtmlEncode(User.Identity.Name));

      }
    }
}



2. Code for UserDetails.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Diagnostics;
using System.Collections.Specialized;


namespace AD
{
    public static class UserDetails
    {
        //Get current user fullname
        public static string GetFullName(string User)
        {
            try
            {
                string currentUser = User;
                System.DirectoryServices.DirectoryEntry entry = new                             System.DirectoryServices.DirectoryEntry((ConfigurationManager.ConnectionStrings["ADConnectionString"]).ToString());
                DirectorySearcher ds = new DirectorySearcher(entry);
                ds.PropertiesToLoad.Add("cn");
                ds.Filter = "(SAMaccountname=" + currentUser + ")";
                SearchResult result = ds.FindOne();
                String username = result.Properties["cn"][0].ToString();
                return username;
            }
            catch (Exception ex)
            {
                return ex.ToString();
            }
        }


        public static List<string> GetUserGroupMembership(string strUser)
        {
            List<string> groups = new List<string>();
            //active directory connection string
            string strConn = ConfigurationManager.ConnectionStrings["ADConnectionString"].ConnectionString;
            try
            {
                DirectoryEntry obEntry = new DirectoryEntry(strConn);
                DirectorySearcher srch = new DirectorySearcher(obEntry, "(sAMAccountName=" + strUser + ")");
                SearchResult res = srch.FindOne();
                if (null != res)
                {
                    DirectoryEntry obUser = new DirectoryEntry(res.Path);
                    // Invoke Groups method.
                    object obGroups = obUser.Invoke("Groups");
                    foreach (object ob in (IEnumerable)obGroups)
                    {
                        // Create object for each group.
                        DirectoryEntry obGpEntry = new DirectoryEntry(ob);
                        groups.Add(obGpEntry.Name);
                    }
                }
                return groups;
            }
            catch (Exception ex)
            {
                Trace.Write(ex.Message);
                return ex.ToString();
            }
        }
    }
}
-----------------

Corrections:
default.aspx --  lblUserGroups.Text = UserDetails.GetUserGroupMembership(Server.HtmlEncode(User.Identity.Name)).ToString();
0
 
Bob LearnedCommented:
GetUserGroupMembership returns a list, so you can't set the Text property for a TextBox to that.  I would use a ListBox to display the groups.

Bob
0
 
fwstealAuthor Commented:
I did this:
default.aspx
<asp:ListBox ID="lbUserGroups" runat="server" />

default.aspx.cs -- set the field name and value
lbUserGroups.DataTextField = UserDetails.GetUserGroupMembership(Server.HtmlEncode(User.Identity.Name)).ToString();
lbUserGroups.DataValueField = UserDetails.GetUserGroupMembership(Server.HtmlEncode(User.Identity.Name)).ToString();

However, I keep getting the same errors on the userdetails.cs file.
Error 2      Using the generic type 'System.Collections.Generic.IEnumerable<T>' requires '1' type arguments      \UserDetails.cs
Error 3      Cannot implicitly convert type 'string' to 'System.Collections.Generic.List<string>'      \UserDetails.cs

0
 
Bob LearnedCommented:
foreach (object ob in (System.Collections.IEnumerable)obGroups)

I am not sure where error 3 is coming from.

Bob
0
 
fwstealAuthor Commented:
change the listbox:

lbUserGroups.DataSource = UserDetails.GetUserGroupMembership(Server.HtmlEncode(User.Identity.Name)).ToString();
lbUserGroups.DataBind();
0
 
Bob LearnedCommented:
lbUserGroups.DataSource = UserDetails.GetUserGroupMembership(Server.HtmlEncode(User.Identity.Name));

Bob
0
 
fwstealAuthor Commented:
I made those changes and it keeps blowing up on:

         public static List<string> GetUserGroupMembership(string strUser)
        {
            List<string> groups = new List<string>();
            //active directory connection string
            string strConn = ConfigurationManager.ConnectionStrings["ADConnectionString"].ConnectionString;
            try
            {
                DirectoryEntry obEntry = new DirectoryEntry(strConn);
                DirectorySearcher srch = new DirectorySearcher(obEntry, "(sAMAccountName=" + strUser + ")");
                SearchResult res = srch.FindOne();
                if (null != res)
                {
                    DirectoryEntry obUser = new DirectoryEntry(res.Path);
                    // Invoke Groups method.
                    object obGroups = obUser.Invoke("Groups");
                    //foreach (object ob in (IEnumerable)obGroups)
                    foreach (object ob in (System.Collections.IEnumerable)obGroups)
                    {
                        // Create object for each group.
                        DirectoryEntry obGpEntry = new DirectoryEntry(ob);
                        groups.Add(obGpEntry.Name);
                    }
                }
                return groups;
            }
            catch (Exception ex)
            {
                Trace.Write(ex.Message);
                return ex.ToString(); //errors here
            }
        }

Cannot implicitly convert type 'string' to 'System.Collections.Generic.List<string>'
0
 
Bob LearnedCommented:
You can't return a string where a List<string> is expected.

 return ex.ToString();

Bob
0
 
fwstealAuthor Commented:
how is it done in a try/catch block?
0
 
Bob LearnedCommented:
I guess you could use something like this:

   return null;

On the receiving end, check for that:

   List<string> groups = UserDetails.GetUserGroupMembership(Server.HtmlEncode(User.Identity.Name));
   if (groups != null)
   {
         lbUserGroups.DataSource = groups;
         lbUserGroups.DataBind();
    }

Bob
0
 
fwstealAuthor Commented:
i did this with the default.aspx.cs and userdetails.cs files
**********************
Default.aspx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Security.Principal;
using System.Text;

using System.Collections.Generic;
using System.DirectoryServices;
using System.Threading;
using System.Diagnostics;
using System.Collections.Specialized;


namespace AD
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                //get user groups
                List<string> groups = new List<string>();
                groups = UserDetails.GetUserGroupMembership(Server.HtmlEncode(User.Identity.Name));
                if (groups != null)
                {
                    lbUserGroups.DataSource = groups;
                    lbUserGroups.DataBind();
                }
                else
                {
                    Response.Redirect("error.aspx");
                }

            }
            catch (Exception ex)
            {
                Response.Redirect("error.aspx");
            }
        }


    }
}

-------------------------------------------
UserDetails.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Diagnostics;
using System.Collections.Specialized;


namespace AD
{
    public static class UserDetails
    {
        private static string strConn = ConfigurationManager.ConnectionStrings["ADConnectionString"].ConnectionString;
       


        //Get current user AD Groups
        public static List<string> GetUserGroupMembership(string strUser)
        {
            List<string> groups = new List<string>();
            //active directory connection string
            try
            {
                DirectoryEntry obEntry = new DirectoryEntry(strConn);
                DirectorySearcher srch = new DirectorySearcher(obEntry, "(sAMAccountName=" + strUser + ")");
                SearchResult res = srch.FindOne();
                if (null != res)
                {
                    DirectoryEntry obUser = new DirectoryEntry(res.Path);
                    // Invoke Groups method.
                    object obGroups = obUser.Invoke("Groups");
                    foreach (object ob in (System.Collections.IEnumerable)obGroups)
                    {
                        // Create object for each group.
                        DirectoryEntry obGpEntry = new DirectoryEntry(ob);
                        groups.Add(obGpEntry.Name);
                    }
                }
                return groups;
            }
            catch (Exception ex)
            {
                Trace.Write(ex.Message);
                return null;
            }
        }



    }
}
**********************

I noticed that my user is in an OU and when I run the above, the listbox is not populated with anything. Shouldn't it have picked up the OU or that the user account is in the Domain Users?
0
 
Bob LearnedCommented:
What does groups.Count equal?

Bob
0
 
fwstealAuthor Commented:
0
0
 
Bob LearnedCommented:
Then, you didn't find any users in that path that you specified.

Bob
0
 
fwstealAuthor Commented:
so what path or group do I need to query?

web.config

<!-- Begin dbconnection settings -->
 <connectionStrings>
  <add name="ADConnectionString" connectionString="LDAP://domaindev.net/DC=domaindev,DC=net" />
 </connectionStrings>
<!-- End dbconnection settings -->
------------------------------------

default.aspx.cs
                //get user groups
                List<string> groups = new List<string>();
                groups = UserDetails.GetUserGroupMembership(Server.HtmlEncode(User.Identity.Name));
                if (groups != null)
                {
                    lbUserGroups.DataSource = groups;
                    lbUserGroups.DataBind();
                }
                else
                {
                    Response.Redirect("error.aspx");
                }
-------------------------------------

userdetails.cs
        //Get current user AD Groups
        public static List<string> GetUserGroupMembership(string strUser)
        {
            List<string> groups = new List<string>();
            //active directory connection string
            try
            {
                DirectoryEntry obEntry = new DirectoryEntry(strConn);
                DirectorySearcher srch = new DirectorySearcher(obEntry, "(sAMAccountName=" + strUser + ")");
                SearchResult res = srch.FindOne();
                if (null != res)
                {
                    DirectoryEntry obUser = new DirectoryEntry(res.Path); //="LDAP://domaindev.net/CN=fname lname,OU=Developers,DC=DomainDev,DC=net"
                    // Invoke Groups method.
                    object obGroups = obUser.Invoke("Groups");
                    foreach (object ob in (System.Collections.IEnumerable)obGroups)
                    {
                        // Create object for each group.
                        DirectoryEntry obGpEntry = new DirectoryEntry(ob);
                        groups.Add(obGpEntry.Name);
                    }
                }
                return groups;
            }
            catch (Exception ex)
            {
                Trace.Write(ex.Message);
                return null;
            }
        }
-------------------------------------


res.Path = "LDAP://dev.net/CN=fname lname,OU=Developers,DC=Dev,DC=net"

0
 
Bob LearnedCommented:
I would use the Developers container, without the CN.

Bob
0
 
fwstealAuthor Commented:
how?
0
 
Bob LearnedCommented:
res.Path = "LDAP://dev.net/OU=Developers,DC=Dev,DC=net"

Bob
0
 
fwstealAuthor Commented:
res.Path is generated automatically when queried by using the webconfig, right?
I changed the web.config from:
<add name="ADConnectionString" connectionString="LDAP://domaindev.net/DC=domaindev,DC=net" />
to:
<add name="ADConnectionString" connectionString="LDAP://domaindev.net/OU=Developers,DC=domaindev,DC=net" />

Still, the groups listbox is not populated.
0
 
fwstealAuthor Commented:
I tried the following and can not log into the domain.

<add name="ADConnectionString" connectionString="LDAP://domaindev.net/CN=Users,DC=domaindev,DC=net" />


0
 
Bob LearnedCommented:
This is where I can't tell you what your LDAP path should be, other than it should be a valid path for the user container for your Active Directory instance.

Bob
0
 
fwstealAuthor Commented:
got it to work; now returns CN=Administrators.

how or where should I remove CN=  in the code? I just want the group name.
0
 
Bob LearnedCommented:
The path specification for groups is to the Users container.  If Administrators is the container, then you just need to something like this maybe:

res.Path = "LDAP://dev.net/CN=Administrators, OU=Developers,DC=Dev,DC=net"

Bob
0
 
fwstealAuthor Commented:
I'd like to keep the path generic - just referring to the domain. This way I can pull back the groups depending on whom ever logs into the site and display there associated groups.

Is there a way to trim the listed groups that are being pulled back so CN= is not in the list?
0
 
Bob LearnedCommented:
What organizational unit are the users stored in?

Bob
0
 
fwstealAuthor Commented:
that can vary; I'm trying to set it up so that it queries AD based on the uid/psswd that was entered during the login process. Once the user logs in, I want to display the groups or OUs that the member is associated with.
0
 
Bob LearnedCommented:
Are you going to have to search through OUs to find the user?

Bob
0
 
fwstealAuthor Commented:
OUs, groups or where the user is found; just want to find the user in AD and report back the groups that the user belongs to. The user could be in OUs and/or groups in AD.
0
 
Bob LearnedCommented:
1) How complex is your Active Directory hierarchy (# of OUs, depth, etc.)?

2) I worked in a large organization, with a lot of OU's, and I came up with this:

using System;
using System.Collections.Generic;
using System.DirectoryServices;

public class ActiveDirectoryUsers
{

    private static SortedList<string, string> LoadOrganizationalUnits()
    {

        SortedList<string, string> listUnits = new SortedList<string, string>();

        DirectorySearcher searchOU = new DirectorySearcher();

        searchOU.PageSize = 1000;
        searchOU.PropertiesToLoad.AddRange(new string[] { "name", "distinguishedName" });
        searchOU.Filter = "objectCategory=organizationalUnit";

        SearchResultCollection resultsAll = searchOU.FindAll();

        foreach (SearchResult resultSingle in resultsAll)
        {

            string basePath = resultSingle.GetDirectoryEntry().Properties["distinguishedName"].Value.ToString();

            listUnits.Add(basePath, basePath);

        }

        return listUnits;

    }

    public static SortedList<string, ActiveUser> LoadUserInfo()
    {

        SortedList<string, ActiveUser> users = new SortedList<string, ActiveUser>();

        SortedList<string, string> units = LoadOrganizationalUnits();

        DirectorySearcher searchUsers = new DirectorySearcher();

        searchUsers.Filter = "(&(objectClass=user)(objectCategory=person))";
        searchUsers.SearchScope = SearchScope.Subtree;

        foreach (SearchResult userResult in searchUsers.FindAll())
        {

            ActiveUser currentUser = new ActiveUser();

            DirectoryEntry currentEntry = userResult.GetDirectoryEntry();

            currentUser.Name = Prop(currentEntry, "cn");
            currentUser.UserName = Prop(currentEntry, "sAMAccountName");
            currentUser.Title = Prop(currentEntry, "title");
            currentUser.EMail = Prop(currentEntry, "mail");
            currentUser.Phone = Prop(currentEntry, "telephoneNumber");
            currentUser.Company = Prop(currentEntry, "company");
            currentUser.Location = Prop(currentEntry, "physicalDeliveryOfficeName");
            currentUser.StreetAddress = Prop(currentEntry, "streetAddress");

            if (currentUser.Name.Length > 0 && !users.ContainsKey(currentUser.Name))
            {
                users.Add(currentUser.Name, currentUser);
            }

        }

        searchUsers.Dispose();

        return users;

    }

    private static string Prop(DirectoryEntry entry, string name)
    {

        string propValue = string.Empty;

        try
        {

            propValue = entry.Properties[name].Value.ToString();
        }

        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            // Ignore error here.

        }

        return propValue;

    }

}

public class ActiveUser
{

    private string m_name = string.Empty;
    public string Name
    {
        get { return m_name; }
        set { m_name = value; }
    }

    private string m_user = "";
    public string UserName
    {
        get { return m_user; }
        set { m_user = value; }
    }

    private string m_title = "";
    public string Title
    {
        get { return m_title; }
        set { m_title = value; }
    }

    private string m_email = "";
    public string EMail
    {
        get { return m_email; }
        set { m_email = value; }
    }

    private string m_company = "";
    public string Company
    {
        get { return m_company; }
        set { m_company = value; }
    }

    private string m_location = "";
    public string Location
    {
        get { return m_location; }
        set { m_location = value; }
    }

    private string m_address = "";
    public string StreetAddress
    {
        get { return m_address; }
        set { m_address = value; }
    }

    private string m_phone = "";
    public string Phone
    {
        get { return m_phone; }
        set { m_phone = value; }
    }

}

Bob
0
 
Computer101Commented:
Forced accept.

Computer101
EE Admin
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.

  • 19
  • 17
Tackle projects and never again get stuck behind a technical roadblock.
Join Now