Solved

Retrieve users in AD using ASP.NET

Posted on 2012-12-20
47
1,370 Views
Last Modified: 2016-10-05
Hello Experts,

I need to be able to retrieve users from AD. I thought that it would be nice if I had a TextBox control that would search AD as I type in the name. This way if it starts searching for names as I type then I can pick the name before I finish type the name.

Is this possible or is there a better solution that I do not know about. I'm also very new to doing stuff like this so please bare with me.

I'm using ASP.NET 4.5, C#, IIS7.5, and Windows Authentication.

Thanks in advance.
0
Comment
Question by:asp_net2
  • 24
  • 11
  • 9
  • +3
47 Comments
 
LVL 11

Expert Comment

by:Mihai Stancescu
Comment Utility
Hi,

Here is a good starting point : article

Check solution at the end.


Regards,
Mishu
0
 
LVL 1

Expert Comment

by:jinsonaf
Comment Utility
Microsoft support
you can find everything you need in this article of microsoft
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@Mishu007,

This is what I was afraid of. Links to tutorials and or articles that do not work. I have tried to produce the same exact thing and all I see are errors and issue with Ajax. I was using ASP.NET 4.5 and I had to switch to 4.0 because that is one of the recomendations in the error or switch to ScriptManager instead of ToolScriptManager but no luck either.

I'm going to post the codebehind and webservice along with the AJAX errors I'm receiving. I could really use some help with this. I have searched google for almost and entire day and no good tutorials out there on this at least none that I can find that work :(

CodeBehind:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Security.Cryptography;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Security;
using System.Text;
using System.Web.Services;

namespace HostControl
{
    public partial class OpenJob
    {
        protected global::AjaxControlToolkit.ToolkitScriptManager ScriptManager1;
        protected global::System.Web.UI.WebControls.TextBox txtUserName;
        protected global::AjaxControlToolkit.AutoCompleteExtender AutoCompleteExtender1;
        protected global::System.Web.UI.WebControls.Button btnGetInfo;
        protected global::System.Web.UI.WebControls.Label lblEmail;
        protected global::System.Web.UI.WebControls.Label lblEmailResult;
        protected global::System.Web.UI.WebControls.Label lblPhone;
        protected global::System.Web.UI.WebControls.Label lblPhoneResult;
    }
}


public partial class tickets_create : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        RetrieveListOfCompanies();
        RetrieveListOfTicketOwners();
        RetrieveListOfRequestTypes();
        //RetrieveListOfUserRequestChange();
    }

    protected void RetrieveListOfCompanies()
    {
        ddlCompany.AppendDataBoundItems = true;

        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CMDB"].ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "RetrieveListOfCompanies";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn;

            try
            {
                conn.Open();

                ddlCompany.DataSource = cmd.ExecuteReader();
                ddlCompany.DataValueField = "com_id";
                ddlCompany.DataTextField = "com_name";
                ddlCompany.DataBind();
            }

            catch (Exception ex)
            {
                ex.Message.ToString();
            }
        }
    }

    protected void RetrieveListOfTicketOwners()
    {
        ddlTicketOwner.AppendDataBoundItems = true;

        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CMDB"].ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "RetrieveListOfTicketOwners";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn;

            try
            {
                conn.Open();

                ddlTicketOwner.DataSource = cmd.ExecuteReader();
                ddlTicketOwner.DataValueField = "ownr_id";
                ddlTicketOwner.DataTextField = "OwnerFullName";
                ddlTicketOwner.DataBind();
            }

            catch (Exception ex)
            {
                ex.Message.ToString();
            }
        }
    }

    protected void RetrieveListOfRequestTypes()
    {
        ddlRequestType.AppendDataBoundItems = true;

        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CMDB"].ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "RetrieveListOfRequestTypes";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn;

            try
            {
                conn.Open();

                ddlRequestType.DataSource = cmd.ExecuteReader();
                ddlRequestType.DataValueField = "req_typ_id";
                ddlRequestType.DataTextField = "req_typ_name";
                ddlRequestType.DataBind();
            }

            catch (Exception ex)
            {
                ex.Message.ToString();
            }
        }
    }

    protected void btnCreateNewTicket_Click(object sender, EventArgs e)
    {
        if (Page.IsValid)
        {
            if (fuAttachFile.HasFile)
            {
                string extension = Path.GetExtension(fuAttachFile.PostedFile.FileName).ToLower();
                string MIMEType = null;

                switch (extension)
                {
                    case ".pdf":
                        MIMEType = "application/pdf";
                        break;
                    case ".doc":
                        MIMEType = "application/msword";
                        break;
                    case ".xls":
                        MIMEType = "application/vnd.ms-excel";
                        break;
                    case ".txt":
                        MIMEType = "text/plain";
                        break;
                    case ".png":
                        MIMEType = "image/png";
                        break;
                    case ".jpg":
                        MIMEType = "image/jpeg";
                        break;
                    case ".jpeg":
                        MIMEType = "image/jpeg";
                        break;
                    case ".vsd":
                        MIMEType = "application/vnd.visio";
                        break;
                    default:
                        lblFileTypeError.Visible = true;
                        lblFileTypeError.Text = "Please choose correct file format.";
                        return;
                }

                string filename = fuAttachFile.PostedFile.FileName.Split(new char[] { '\\' }).Last();
                int fileSize = fuAttachFile.PostedFile.ContentLength;

                if ((fileSize < 1048576))
                {
                    SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CMDB"].ConnectionString);

                    SqlCommand cmd = new SqlCommand();
                    cmd.CommandText = "InsertNewTicket";
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Connection = conn;

                    // Load InputStream into Byte array
                    byte[] imageBytes = new byte[fuAttachFile.PostedFile.InputStream.Length + 1];
                    fuAttachFile.PostedFile.InputStream.Read(imageBytes, 0, imageBytes.Length);

                    //cmd.Parameters.AddWithValue("@usr_req_chg_id", SqlDbType.Int).Value = ddlUserRequestingChange.SelectedItem.Value;
                    cmd.Parameters.AddWithValue("@req_typ_id", SqlDbType.Int).Value = ddlRequestType.SelectedItem.Value;
                    cmd.Parameters.AddWithValue("@com_id", SqlDbType.Int).Value = ddlCompany.SelectedItem.Value;
                    cmd.Parameters.AddWithValue("@ownr_id", SqlDbType.Int).Value = ddlTicketOwner.SelectedItem.Value;
                    cmd.Parameters.AddWithValue("@tkt_desc", SqlDbType.VarChar).Value = txtTicketDesc.Text;
                    cmd.Parameters.AddWithValue("@tkt_file", SqlDbType.Image).Value = imageBytes;
                    cmd.Parameters.AddWithValue("@tkt_filename", SqlDbType.VarChar).Value = filename;
                    cmd.Parameters.AddWithValue("@tkt_mime", SqlDbType.VarChar).Value = MIMEType;
                    cmd.Parameters.AddWithValue("@tkt_size", SqlDbType.VarChar).Value = fileSize;
                    cmd.Parameters.AddWithValue("@sts_id", SqlDbType.Int).Value = 71;

                    string username = User.Identity.Name;
                    if (username.Contains('\\'))
                    { username = username.Split('\\')[1]; }

                    cmd.Parameters.AddWithValue("@tkt_cre_user", SqlDbType.VarChar).Value = username;

                    try
                    {
                        conn.Open();
                        cmd.ExecuteNonQuery();
                    }

                    catch (Exception ex)
                    {
                        lblInsertError.Visible = true;
                        lblInsertError.Text = ("Error on insert: " + ex.Message.ToString());
                    }

                    finally
                    {
                        Response.Redirect("index.aspx");
                        conn.Close();
                    }
                }

                else
                {
                    lblFileSize.Visible = true;
                    lblFileSize.Text = "File size must be 1MB or smaller.";
                }
            }
            else  // no file has been uploaded, we only need to update txtPhysicalDateCompleted
            {
                SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CMDB"].ConnectionString);

                SqlCommand cmd = new SqlCommand();
                cmd.CommandText = "InsertNewTicket";
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Connection = conn;

                byte[] imageBytes = new byte[1];

                //cmd.Parameters.AddWithValue("@usr_req_chg_id", SqlDbType.Int).Value = ddlUserRequestingChange.SelectedItem.Value;
                cmd.Parameters.AddWithValue("@req_typ_id", SqlDbType.Int).Value = ddlRequestType.SelectedItem.Value;
                cmd.Parameters.AddWithValue("@com_id", SqlDbType.Int).Value = ddlCompany.SelectedItem.Value;
                cmd.Parameters.AddWithValue("@ownr_id", SqlDbType.Int).Value = ddlTicketOwner.SelectedItem.Value;
                cmd.Parameters.AddWithValue("@tkt_desc", SqlDbType.VarChar).Value = txtTicketDesc.Text;
                cmd.Parameters.AddWithValue("@tkt_file", SqlDbType.Image).Value = imageBytes;
                cmd.Parameters.AddWithValue("@tkt_filename", SqlDbType.VarChar).Value = "";
                cmd.Parameters.AddWithValue("@tkt_mime", SqlDbType.VarChar).Value = "application/octet-stream";
                cmd.Parameters.AddWithValue("@tkt_size", SqlDbType.VarChar).Value = 0;
                cmd.Parameters.AddWithValue("@sts_id", SqlDbType.Int).Value = 71;

                string username = User.Identity.Name;

                if (username.Contains('\\'))
                { username = username.Split('\\')[1]; }

                cmd.Parameters.AddWithValue("@tkt_cre_user", SqlDbType.VarChar).Value = username;

                try
                {
                    conn.Open();
                    cmd.ExecuteNonQuery();
                }

                catch (Exception ex)
                {
                    lblInsertError.Visible = true;
                    lblInsertError.Text = ("Error on insert: " + ex.Message.ToString());
                }

                finally
                {
                    Response.Redirect("index.aspx");
                    conn.Close();
                }
            }
        }
    }
}

Open in new window


AJAX Error:
Unhandled exception at line 3, column 412 in http://localhost:49426/CMDB/tickets/create.aspx?_TSM_HiddenField_=ToolkitScriptManager1_HiddenField&_TSM_CombinedScripts_=;;AjaxControlToolkit,+Version=4.1.60919.0,+Culture=neutral,+PublicKeyToken=28f01b0e84b6d53e:en-US:ee051b62-9cd6-49a5-87bb-93c07bc43d63:de1feab2:f2c8e708:720a52bf:f9cec9bc:589eaa30:698129cf:7a92f56c

0x800a139e - Microsoft JScript runtime error: AjaxControlToolkit requires ASP.NET Ajax 4.0 scripts. Ensure the correct version of the scripts are referenced. If you are using an ASP.NET ScriptManager, switch to the ToolkitScriptManager in AjaxControlToolkit.dll.

Open in new window


If I continue at the error above then I have another error below:
Unhandled exception at line 205, column 5 in http://localhost:49426/CMDB/tickets/create.aspx

0x800a138f - Microsoft JScript runtime error: Unable to get value of the property 'UI': object is null or undefined

Open in new window


The line of code that this refers to is listed below.
 $create(Sys.Extended.UI.AutoCompleteBehavior, {"delimiterCharacters":"","id":"AutoCompleteExtender1","serviceMethod":"finduser","servicePath":"WebService.asmx"}, null, null, $get("txtUserName"));

Open in new window

0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@jinsonaf,

The link you supplied has to do with authentication against AD. I don't need that, I need to auto populate users from AD as you type them out in a TextBox control. Just as when you enter search words in Google, the words start to appear as you type.
0
 
LVL 12

Expert Comment

by:jagssidurala
Comment Utility
We can implement Autopopulation with JQuery,

refer this link

http://www.aspsnippets.com/articles/using-jquery-autocomplete-plugin-in-asp.net.aspx

In .ashx, write a code to retrive Users from AD.
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@jaqssidurala,

Ok, I understand the jquery part at least it seems self explanatory. The problem that I still need help is the code for AD retrieval. I simple need to populate the list of all users in that textbox control as you type in the name it will search AD and show list of possible matches to choose from. That is what I really need help with.
0
 
LVL 83

Expert Comment

by:CodeCruiser
Comment Utility
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@CodeCruiser,

I implemented the second link you supplied and it did not autocomplete as I typed in the TextBox Control. I did not retrieve anything from Active Directory. I also did not receive any sort of errors. Please take a look at my CodeBehind and Markup.

Also, the name of my AD server is called occo.local

CodeBehind:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.DirectoryServices; 

/// <summary>
/// Summary description for ADS
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
// [System.Web.Script.Services.ScriptService]
public class ADS : System.Web.Services.WebService {

    [WebMethod]
    public string[] findEmp(string prefixText, int count)
    {
        System.DirectoryServices.DirectoryEntry directory = new System.DirectoryServices.DirectoryEntry();
        directory.Path = "LDAP://occo.local";  //CHANGE to your LDAP path
        string filter = "(&(cn=" + prefixText + "*))";
        string[] strCats = { "cn" };
        List<string> items = new List<string>();
        System.DirectoryServices.DirectorySearcher dirComp = new System.DirectoryServices.DirectorySearcher(directory, filter, strCats, System.DirectoryServices.SearchScope.Subtree);
        System.DirectoryServices.SearchResultCollection results = dirComp.FindAll();

        foreach (SearchResult result in results)
        {
            foreach (DictionaryEntry prop in result.Properties)
            {
                if (prop.Key.Equals("cn"))
                {
                    System.Collections.IEnumerable propsEnum = prop.Value as System.Collections.IEnumerable;
                    foreach (object individualValue in propsEnum)
                    {
                        if (individualValue.ToString().IndexOf(prefixText) != 0)
                        {
                            items.Add(individualValue.ToString());
                        }
                    }
                }
            }
        }
        return items.ToArray();
    }
}

Open in new window


Markup:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server"></asp:ToolkitScriptManager>
    <div>
        <asp:TextBox ID="txtUserName" runat="server"></asp:TextBox>
                <asp:AutoCompleteExtender ID="AutoCompleteExtender1" ServiceMethod="findEmp"
MinimumPrefixLength="3"
CompletionInterval="100"
EnableCaching="true"
CompletionSetCount="10"
TargetControlID="txtUserName"
 runat="server" FirstRowSelected="false" ServicePath="~/App_Code/ADS.cs"></asp:AutoCompleteExtender>
    <br /> 
    </div>
    </form>
</body>
</html>

Open in new window

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.DirectoryServices; 

/// <summary>
/// Summary description for ADS
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
// [System.Web.Script.Services.ScriptService]
public class ADS : System.Web.Services.WebService {

    [WebMethod]
    public string[] findEmp(string prefixText, int count)
    {
        System.DirectoryServices.DirectoryEntry directory = new System.DirectoryServices.DirectoryEntry();
        directory.Path = "LDAP://DC=yourdomain,DC=com";  //CHANGE to your LDAP path
        string filter = "(&(cn=" + prefixText + "*))";
        string[] strCats = { "cn" };
        List<string> items = new List<string>();
        System.DirectoryServices.DirectorySearcher dirComp = new System.DirectoryServices.DirectorySearcher(directory, filter, strCats, System.DirectoryServices.SearchScope.Subtree);
        System.DirectoryServices.SearchResultCollection results = dirComp.FindAll();

        foreach (SearchResult result in results)
        {
            foreach (DictionaryEntry prop in result.Properties)
            {
                if (prop.Key.Equals("cn"))
                {
                    System.Collections.IEnumerable propsEnum = prop.Value as System.Collections.IEnumerable;
                    foreach (object individualValue in propsEnum)
                    {
                        if (individualValue.ToString().IndexOf(prefixText) != 0)
                        {
                            items.Add(individualValue.ToString());
                        }
                    }
                }
            }
        }
        return items.ToArray();
    }
}

Open in new window

0
 
LVL 83

Expert Comment

by:CodeCruiser
Comment Utility
>ServicePath="~/App_Code/ADS.cs">

Service path needs to be a URL of a webservice which usually ends in asmx extension not cs.
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@CodeCruiser,

Ok, I now have the ServicePath set to the following below. But when I try to type in a username, firstname, and or lastname. Nothing is getting displayed :(

ServicePath="~/ADS.asmx"
0
 
LVL 83

Expert Comment

by:CodeCruiser
Comment Utility
If you type that URL in, does it browse to the webservice? Is the webservice at same level as your page in IIS? If you set a breakpoint on findEmp method, is it being called?
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
>>If you type that URL in, does it browse to the webservice?
If I type in the site on my local browser I see the following URL below and Screenshot.

URL in Browser window after typing in the webservice URL.
http://localhost:51190/AD%20test/ads.asmx?op=findEmp

Screenshot below after typing in the URL to the webservice below.
screenshot

>> If you set a breakpoint on findEmp method, is it being called?
If I set a breakpoint on the findEmp method nothing happens. There are no errors shown in Visual Studio. It appears that the breakpoint did not even exist. Just to be certain I applied a break point on the line below.

Breakpoint was set on this line.
public string[] findEmp(string prefixText, int count)
0
 
LVL 83

Expert Comment

by:CodeCruiser
Comment Utility
Breakpoint needs to be set on a line within the function not the function declaration line itself.

Is your page within "AD test" folder as well?
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
Hi CodeCruiser,

First let me know you tremendously for your help with this post. This is a topic that I know very little about. I never needed to do anything like this until now and it's very unclear and hard to follow tutorials on the web. Which leaves me to EE for this topic. So thank you very much for your continued help...

>> Breakpoint needs to be set on a line within the function not the function declaration line itself.
I added multiple breakpionts. But no matter where I set the breakpont at nothing ever popups up to display anything. Nor are there any errors :(


>> Is your page within "AD test" folder as well?
I'm going to list my structure of my web site below. This way you can see how and where my files are located.

rootDirectory
  App_Code
      ADS.cs
  ADS.asmx
  index.aspx
  web.config
0
 
LVL 83

Expert Comment

by:CodeCruiser
Comment Utility
I have tried to create a sample myself but could not get the webservice approach to work. Instead I have used PageMethod approach. I used following code which worked (breakpoint hit)


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="WebApplication3.index" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajax" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <ajax:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" ></ajax:ToolkitScriptManager>
    <div>
        <asp:TextBox ID="txtUserName" runat="server" AutoCompleteType="None"></asp:TextBox>
                <ajax:AutoCompleteExtender ID="AutoCompleteExtender1" ServiceMethod="findEmp"
MinimumPrefixLength="2"
CompletionInterval="100"
EnableCaching="true"
CompletionSetCount="10"
TargetControlID="txtUserName"
 runat="server" ></ajax:AutoCompleteExtender>
    <br /> 
    </div>
    </form>
</body>
</html>

Open in new window




using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

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

        }

        [System.Web.Services.WebMethod]
        public static string[] findEmp(string prefixText, int count)
        {
            List<string> items = new List<string>();
            return items.ToArray();
        }
    }
}

Open in new window



>First let me know you tremendously for your help with this post.

Assuming you meant "Thank", I would be glad if this works for you.
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
Hi CodeCruiser,

Yes, I meant, Thank you :) I really appreciate the help.

Ok, so I added the code you suggested on my index.aspx page and CodeBehind but when I run the page I don't see anything getting populated in the TextBox as I type. I'm also confused as how this will work without adding any code to the Page Methods. I also noticed you removed the webservice from the AutoExtendor Ajax control.

Also, I see you have this in the index.aspx page Inherits="WebApplication3.index". Did you forget to include the code for webapplication3.index?
0
 
LVL 83

Expert Comment

by:CodeCruiser
Comment Utility
>I don't see anything getting populated in the TextBox as I type

That's because there is nothing being returned from the method. Does it hit a breakpoint?

>I'm also confused as how this will work without adding any code to the Page Methods.

I removed that code because I don't have any AD on my computer and it was a demo.

>I also noticed you removed the webservice from the AutoExtendor Ajax control.

Yes. Removing that makes it work with page method.

>Also, I see you have this in the index.aspx page Inherits="WebApplication3.index". Did you forget to include the code for webapplication3.index?

index is the name of the page. WebApplication3 has to be added as it was the namespace. Change that to your own project name.
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
Sorry, I'm confused. The name of my page that contains the Ajax control and codebehind is called index.aspx. So i'm not sure what I should call the namespace.

Below is what I currently have for my CodeBehind and Markup. I also set a breakpoint on each line of the code you supplied in the codebehind but when I run the page nothing is error shown from the textbox nor are there any errors or messages shown from visual studo. It's like the breakpoints are not even working.

Markup:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server"></asp:ToolkitScriptManager>
    <div>
        <asp:TextBox ID="txtUserName" runat="server"></asp:TextBox>
        <asp:AutoCompleteExtender ID="AutoCompleteExtender1" ServiceMethod="findEmp" MinimumPrefixLength="3" CompletionInterval="100" EnableCaching="true" CompletionSetCount="10"
            TargetControlID="txtUserName" runat="server" FirstRowSelected="false"></asp:AutoCompleteExtender>
    <br /> 
    </div>
    </form>
</body>
</html>

Open in new window


CodeBehind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Services;


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

        }

        [System.Web.Services.WebMethod]
        public static string[] findEmp(string prefixText, int count)
        {
            List<string> items = new List<string>();
            return items.ToArray();
        }
    }

Open in new window

0
 
LVL 83

Expert Comment

by:CodeCruiser
Comment Utility
Change it to

Inherits="index"
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
That is what I had in my last post. "Inherits="index"" and that didn't do anything differently. Take a look at my post 38722012.
0
 
LVL 83

Expert Comment

by:CodeCruiser
Comment Utility
As I said, it will NOT do anything because there is no code in there.

Set a breakpoint and see if that breakpoint gets hit. If it does, put your original code backin and see if it does something.
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
Ok, I set a breakpoint on every line and the breakpoint did NOT get hit.
0
 
LVL 83

Expert Comment

by:CodeCruiser
Comment Utility
Ok. It looks like it does not want to work then. It worked in my sample.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 4

Author Comment

by:asp_net2
Comment Utility
Any other ideas CodeCruiser.
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
I was able to get the following below to work but with a couple of problems.

Markup:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %>

<%--<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>--%>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="jquery-ui-1.9.2.custom.min.css" rel="stylesheet" />

    <script src="Scripts/jquery-1.8.3.js"></script>
    <script src="Scripts/jquery-ui-1.9.2.custom.min.js"></script>
    <script src="Scripts/jquery-ui-1.9.2.custom.js"></script>
    <script>
        $(function () { var availableTags = ["ActionScript", "AppleScript", "Asp", "BASIC", "C", "C++", "Clojure", "COBOL", "ColdFusion", "Erlang", "Fortran", "Groovy", "Haskell", "Java", "JavaScript", "Lisp", "Perl", "PHP", "Python", "Ruby", "Scala", "Scheme"]; $("#tags").autocomplete({ source: availableTags }); });
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <input id="tags" />


<%--        <asp:ToolkitScriptManager ID="ToolkitScriptManager1" EnablePageMethods="True" runat="server"></asp:ToolkitScriptManager>
        <asp:TextBox ID="txtADSearch" runat="server"></asp:TextBox>
        <asp:AutoCompleteExtender ID="AutoCompleteExtender1" 
            ServiceMethod="findit" 
            MinimumPrefixLength="3" 
            CompletionInterval="100" 
            EnableCaching="true" 
            CompletionSetCount="10" 
            TargetControlID="txtADSearch" 
            FirstRowSelected="false"
            ServicePath="~/ADS.asmx" 
            runat="server">
        </asp:AutoCompleteExtender>--%>


    </form>

</body>
</html>

Open in new window


Issues below:
  - The data populated once you type in the textbox control disappears if I try to select an entry using my mouse or arrow keys.

  - Still need help with connecting this to the webservice.
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@Mishu007,

I tried your solution to the link you supplied and did NOT have any luck at all. No errors and no data got populated in the TextBox. Do you know how to implement autocomplete without using AJAX? Do you know how to get this to work using jquery autocomplete and pointing to webservice? Please no links or tutorials. That takes to much time and leads to no were.
0
 
LVL 11

Expert Comment

by:Mihai Stancescu
Comment Utility
Hi,

Sorry for long delay....

You can use jQuery to autocomplete the textbox. To use jquery you must have a web service that will transform the AD users into json and then put that address of the method into the jquery definition for autocomplete and all should work ok.

I'm sorry I know you said no links but unfortunately I can't provide a full example right now.

Here is a link that I think will be fast and easy to understand and implement.

ASPX Autocomplete using Jquery UI

Sorry again for not providing a sample myself.


Regards,
Mishu
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@Mish007,

Thanks for replying back. I have been looking at your first post with the link at the bottom solution and I have been having a hell of a time trying to get that to work. I tried once again just now after adding jquery autocomplete but with no success. Would you please be able to look over my ADS.asmx code to see what it's not populating results from my Active Directory? I know you don't have access to my Active Directory but was hopiong you may see someting that may help me out. I would really appreciate it. I have been able to populate data using the jquery autocomplete will sample data just not with my ADS.asmx code.

The ADS.asmx code below is from your link that you supplied to me in your first post. It was taken from the solution except at the bottom of that page. I need to be able to retrieve First and Last Names from AD when the user starts to type in the TextBox control.

HTML Markup:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="jquery-ui-1.9.2.custom.min.css" rel="stylesheet" />

    <script src="Scripts/jquery-1.8.3.js"></script>
    <script src="Scripts/jquery-ui-1.9.2.custom.min.js"></script>
    <script src="Scripts/jquery-ui-1.9.2.custom.js"></script>
    <script type="text/javascript">
        $(function () {
            $('#<%= txtName.ClientID %>').autocomplete({
                source: "ADS.asmx"
            });
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <asp:TextBox ID="txtName" runat="server"></asp:TextBox>
    </form>
</body>
</html>

Open in new window


ADS.asmx Code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.DirectoryServices;

namespace HostControl
{
    [WebService(Namespace = "http://localhost/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.Web.Script.Services.ScriptService]
    public class ads : System.Web.Services.WebService
    {
        [WebMethod]
        public string[] findit(string prefixText, int count)
        {
            DirectoryEntry directory = new DirectoryEntry("LDAP://n-acdir:389");
            string filter = "(&(cn=" + prefixText + "*))";
            string[] strCats = { "cn" };
            List<string> items = new List<string>();
            DirectorySearcher dirComp = new DirectorySearcher(directory, filter, strCats, SearchScope.Subtree);
            SearchResultCollection results = dirComp.FindAll();
            foreach (SearchResult result in results)
            {
                foreach (DictionaryEntry prop in result.Properties)
                {
                    if (prop.Key.Equals("cn"))
                    {
                        System.Collections.IEnumerable propsEnum = prop.Value as System.Collections.IEnumerable;
                        foreach (object individualValue in propsEnum)
                        {
                            if (individualValue.ToString().IndexOf(prefixText) != 0)
                            {
                                items.Add(individualValue.ToString());
                            }
                        }
                    }
                }
            }

            return items.ToArray();
        }
    }

}

Open in new window

0
 
LVL 11

Expert Comment

by:Mihai Stancescu
Comment Utility
Hi,

If you are using the JQuery approach you can use it like this (from my second example link):

$('#<%= txtName.ClientID %>').autocomplete({
                source: function(request, response) {
            $.ajax({
                url: "ADS.asmx/findit",
                data: "{ 'prefixText': '" + request.term + "' }",
                dataType: "json",
                type: "POST",
                contentType: "application/json; charset=utf-8",
                dataFilter: function(data) { return data; },
                success: function(data) {
                    response($.map(data.d, function(item) {
                        return {
                            value: item
                        }
                    }))
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    alert(textStatus);
                }
            });
        }, 
        minLength: 2 
    });

Open in new window


Also you may need to change the findit declaration to have only one parameter the string one, or map it in the data parameter in the jQuery definition.

I'm very sorry but I can't test this right now because I'm on the run ... but it should work...

Also have a look into this article regarding AD query using C# Howto Almost Everything In Active Directory via C#, especially at the Translate the Friendly Domain Name to Fully Qualified Domain.

public static string FriendlyDomainToLdapDomain(string friendlyDomainName)
{
    string ldapPath = null;
    try
    {
        DirectoryContext objContext = new DirectoryContext(
            DirectoryContextType.Domain, friendlyDomainName);
        Domain objDomain = Domain.GetDomain(objContext);
        ldapPath = objDomain.Name;
    }
    catch (DirectoryServicesCOMException e)
    {
        ldapPath = e.Message.ToString();
    }
    return ldapPath;
}

Open in new window


Regards,
Mishu
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@Mishu007,

Ok, thanks. I added the jquery that you supplied and I did not have any issues with the jquery this time. But, I still cannot get any data to autocomplete with the ADS.asmx code that I have. I tried your code snippet and looked at the URL that you supplied but it did not supply any data to autocomplete either :(

I know your on the run but could you possible assist when you have time? It would be greatly appreciated. When I added the code you supplied I had redlines on "string" and a red line on "DirectoryContext" and also a red line after the "}" character. Each re line says the following below. What I need is when the user enters an employees last name and or first name that it will autocomplete a list of users in AD. Then the user can select with his/her mouse to select the correct user from autocomplete.

Error:
Expected class, delegate, enum, interface, or struct
0
 
LVL 11

Expert Comment

by:Mihai Stancescu
Comment Utility
Hi,

Here is what I got to find ad users that starts with a string...

For framework 2.0:
public static string GetDomainDN(string domain)
        {
            DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
            Domain d = Domain.GetDomain(context);
            DirectoryEntry de = d.GetDirectoryEntry();
            return de.Properties["DistinguishedName"].Value.ToString();
        }

        public static List<string> GetADUsers2_0(string searchTerm)
        {
            List<string> res = new List<string>();
            // define a directory searcher for your default context
            string searchRootLDAPPath = GetDomainDN(Domain.GetCurrentDomain().Name);
            using (DirectoryEntry defaultDE = new DirectoryEntry(String.Format("LDAP://{0}", searchRootLDAPPath)))
            {
                // define searcher - search through entire subtree, search for users 
                // (objectCategory=Person)           
                using (DirectorySearcher dsAllUsers = new DirectorySearcher(defaultDE))
                {
                    dsAllUsers.SearchScope = SearchScope.Subtree;
                    dsAllUsers.Filter = String.Format("(&(objectCategory=person)(objectClass=user)(cn={0}*))", searchTerm);

                    // get the results
                    SearchResultCollection result = dsAllUsers.FindAll();

                    foreach (SearchResult searchResult in result)
                    {
                        res.Add(searchResult.GetDirectoryEntry().Name.Remove(0, 3)); //removing the CN=
                    }

                }
            }
            return res;
        }

Open in new window


Also include the assembly System.DirectoryServices into the project.

For .Net Framework 3.5 and above (works both solutions here):
private static List<string> GetADUsers(string searchTerm)
        {
            List<string> res = new List<string>();
            using (var context = new PrincipalContext(ContextType.Domain, Domain.GetCurrentDomain().Name))
            {
                // create a principal object representation to describe
                // what will be searched 
                UserPrincipal user = new UserPrincipal(context);

                // define the properties of the search (this can use wildcards)
                user.Enabled = true;
                user.Name = String.Format("{0}*", searchTerm);

                // create a principal searcher for running a search operation
                using (PrincipalSearcher pS = new PrincipalSearcher())
                {

                    // assign the query filter property for the principal object 
                    // you created
                    // you can also pass the user principal in the 
                    // PrincipalSearcher constructor
                    pS.QueryFilter = user;

                    // run the query
                    PrincipalSearchResult<Principal> results = pS.FindAll();
                    
                    foreach (Principal result in results)
                    {
                        res.Add(result.Name);
                    }
                }

            }
            return res;
        }

Open in new window

In order for this to work you have to add reference to System.DirectoryServices.AccountManagement.

I've tried this in my current domain and it works great.

Try and use this in the web service to see if it's working or even in a console application to test it out. Maybe you need some credentials to access the AD.

Regards,
Mishu
0
 
LVL 11

Expert Comment

by:Mihai Stancescu
Comment Utility
Hi,

Here is an example I've modified for you and it works ok on my domain.

I don't remember exactly where I got the initial sample. It only had the employee list. And one of the problem was that I was setting the static on the web method.

WebService.cs
public static string GetDomainDN(string domain)
    {
        DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
        Domain d = Domain.GetDomain(context);
        DirectoryEntry de = d.GetDirectoryEntry();
        return de.Properties["DistinguishedName"].Value.ToString();
    }

    [WebMethod]
    public List<string> GetADUsers(string term)
    {
        List<string> res = new List<string>();
        // define a directory searcher for your default context

        string searchRootLDAPPath = GetDomainDN(Domain.GetCurrentDomain().Name);
        using (DirectoryEntry defaultDE = new DirectoryEntry(String.Format("LDAP://{0}", searchRootLDAPPath)))
        {
            // define searcher - search through entire subtree, search for users 
            // (objectCategory=Person)           
            using (DirectorySearcher dsAllUsers = new DirectorySearcher(defaultDE))
            {
                dsAllUsers.SearchScope = SearchScope.Subtree;
                dsAllUsers.Filter = String.Format("(&(objectCategory=person)(objectClass=user)(cn={0}*))", term);

                // get the results
                SearchResultCollection result = dsAllUsers.FindAll();

                foreach (SearchResult searchResult in result)
                {
                    res.Add(searchResult.GetDirectoryEntry().Name.Remove(0, 3)); //removing the CN=
                }

            }
        }

        return res;
    }

Open in new window


Aspx Markup
<script type="text/javascript">
	    $(function() {
	        $("#<%= txtName.ClientID %>").autocomplete({
	            source: function(request, response) {
	                $.ajax({
	                    url: "ADS.asmx/GetADUsers",
	                    data: "{ 'term': '" + request.term + "' }",
	                    dataType: "json",
	                    type: "POST",
	                    contentType: "application/json; charset=utf-8",
	                    dataFilter: function(data) { return data; },
	                    success: function(data) {
	                        response($.map(data.d, function(item) {
	                            return {
	                                value: item
	                            }
	                        }))
	                    },
	                    error: function(XMLHttpRequest, textStatus, errorThrown) {
	                        alert(textStatus);
	                    }
	                });
	            },
	            minLength: 2
	        });
	    });
	</script>

Open in new window


Hope this helps....

Regards,
Mishu
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@Mishu007,

Ok, this time I'm getting a javascript popup error that says "". Please see my modified webservice.asmx code below along with the markup below.

Webservice.cs:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.DirectoryServices.AccountManagement;

    [WebService(Namespace = "http://localhost")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.Web.Script.Services.ScriptService]
    public class ads : System.Web.Services.WebService
    {
        [WebMethod]
        public static string GetDomainDN(string domain)
        {
            DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
            Domain d = Domain.GetDomain(context);
            DirectoryEntry de = d.GetDirectoryEntry();
            return de.Properties["DistinguishedName"].Value.ToString();
        }

        [WebMethod]
        public List<string> GetADUsers(string term)
        {
            List<string> res = new List<string>();
            // define a directory searcher for your default context

            string searchRootLDAPPath = GetDomainDN(Domain.GetCurrentDomain().Name);
            using (DirectoryEntry defaultDE = new DirectoryEntry(String.Format("LDAP://{0}", searchRootLDAPPath)))
            {
                // define searcher - search through entire subtree, search for users 
                // (objectCategory=Person)           
                using (DirectorySearcher dsAllUsers = new DirectorySearcher(defaultDE))
                {
                    dsAllUsers.SearchScope = SearchScope.Subtree;
                    dsAllUsers.Filter = String.Format("(&(objectCategory=person)(objectClass=user)(cn={0}*))", term);

                    // get the results
                    SearchResultCollection result = dsAllUsers.FindAll();

                    foreach (SearchResult searchResult in result)
                    {
                        res.Add(searchResult.GetDirectoryEntry().Name.Remove(0, 3)); //removing the CN=
                    }

                }
            }
            return res;
        }
    }

Open in new window


Markup:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="jquery-ui-1.9.2.custom.min.css" rel="stylesheet" />
    <script src="Scripts/jquery-1.8.3.js"></script>
    <script src="Scripts/jquery-ui-1.9.2.custom.min.js"></script>
    <script src="Scripts/jquery-ui-1.9.2.custom.js"></script>
<script type="text/javascript">
    $(function () {
        $("#<%= txtName.ClientID %>").autocomplete({
	            source: function (request, response) {
	                $.ajax({
	                    url: "ADS.asmx/GetADUsers",
	                    data: "{ 'term': '" + request.term + "' }",
	                    dataType: "json",
	                    type: "POST",
	                    contentType: "application/json; charset=utf-8",
	                    dataFilter: function (data) { return data; },
	                    success: function (data) {
	                        response($.map(data.d, function (item) {
	                            return {
	                                value: item
	                            }
	                        }))
	                    },
	                    error: function (XMLHttpRequest, textStatus, errorThrown) {
	                        alert(textStatus);
	                    }
	                });
	            },
	            minLength: 2
	        });
	    });
	</script>
</head>
<body>
    <form id="form1" runat="server">
        <asp:TextBox ID="txtName" runat="server"></asp:TextBox>
    </form>
</body>
</html>

Open in new window


Error when I run page after typing in at least 2 characters:
When I run the page at put in at least two characters in the TextBox control I keep getting a javascript popup that says "Ok".
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.DirectoryServices.AccountManagement;

    [WebService(Namespace = "http://www.nndsonline.org")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.Web.Script.Services.ScriptService]
    public class ads : System.Web.Services.WebService
    {
        [WebMethod]
        public static string GetDomainDN(string domain)
        {
            DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
            Domain d = Domain.GetDomain(context);
            DirectoryEntry de = d.GetDirectoryEntry();
            return de.Properties["DistinguishedName"].Value.ToString();
        }

        [WebMethod]
        public List<string> GetADUsers(string term)
        {
            List<string> res = new List<string>();
            // define a directory searcher for your default context

            string searchRootLDAPPath = GetDomainDN(Domain.GetCurrentDomain().Name);
            using (DirectoryEntry defaultDE = new DirectoryEntry(String.Format("LDAP://{0}", searchRootLDAPPath)))
            {
                // define searcher - search through entire subtree, search for users 
                // (objectCategory=Person)           
                using (DirectorySearcher dsAllUsers = new DirectorySearcher(defaultDE))
                {
                    dsAllUsers.SearchScope = SearchScope.Subtree;
                    dsAllUsers.Filter = String.Format("(&(objectCategory=person)(objectClass=user)(cn={0}*))", term);

                    // get the results
                    SearchResultCollection result = dsAllUsers.FindAll();

                    foreach (SearchResult searchResult in result)
                    {
                        res.Add(searchResult.GetDirectoryEntry().Name.Remove(0, 3)); //removing the CN=
                    }

                }
            }
            return res;
        }
    }

Open in new window

0
 
LVL 11

Accepted Solution

by:
Mihai Stancescu earned 500 total points
Comment Utility
Hi,

Here is my complete example that works.


It should work ok on your domain too.

Also rename the file ADS to ADS.asmx (can't attach it on EE).

Regards,
Mishu
Example.zip
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@Mishu007,

I added your example and opened it in Visual Studio. I did not modify it and when I ran the application I get the same issue as before. When I type two characters I get a Javascript popup window. Please see the attached screenshot. If I type only 1 character then everything is fine. It's only when I type 2 or more characters.

ee
0
 
LVL 11

Expert Comment

by:Mihai Stancescu
Comment Utility
Hi,

Replace the web service method with this:

 [WebMethod]
    public List<string> GetADUsers(string term)
    {
        List<string> res = new List<string>();
        // define a directory searcher for your default context

        try
        {
            string searchRootLDAPPath = GetDomainDN(Domain.GetCurrentDomain().Name);
            using (DirectoryEntry defaultDE = new DirectoryEntry(String.Format("LDAP://{0}", searchRootLDAPPath)))
            {
                // define searcher - search through entire subtree, search for users 
                // (objectCategory=Person)           
                using (DirectorySearcher dsAllUsers = new DirectorySearcher(defaultDE))
                {
                    dsAllUsers.SearchScope = SearchScope.Subtree;
                    dsAllUsers.Filter = String.Format("(&(objectCategory=person)(objectClass=user)(cn={0}*))", term);

                    // get the results
                    SearchResultCollection result = dsAllUsers.FindAll();

                    foreach (SearchResult searchResult in result)
                    {
                        res.Add(searchResult.GetDirectoryEntry().Name.Remove(0, 3)); //removing the CN=
                    }

                }
            }
        }
        catch (Exception ex)
        {
            res.Add(String.Format("Error: {0}", ex.Message));
        }

        return res;
    }

Open in new window

The error message occurs when you are not in a domain. At least in my part. At work where I am in a domain works great.

Regards,
Mishu
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
Hi Mishu007,

Ok, I modified the code to what you posted above. Unfortunetly I get the same result. I see that you mentioned that I need to be in my domain for this to work. I'm actually working from home on my personal laptop using a VPN to my network since I started this post. I go back to the office this Thursday so I can see if it works then. But I was wondering would it work if I supplied the LDAP path rather than how it is now, would that make a difference since I'm working from home? We have some users who use they computer issued by us but work from home. Will that be a problem for them?

Also, what is the difference to the following below?

What I was trying to use from the tutorial:
"LDAP://n-acdir:389"

What you are using:
"LDAP://{0}"
0
 
LVL 11

Expert Comment

by:Mihai Stancescu
Comment Utility
Hi,

You could specify directly the LDAP connection string but I advise to use this method to return the qualified domain name.

public static string GetDomainDN(string domain)
    {
        DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
        Domain d = Domain.GetDomain(context);
        DirectoryEntry de = d.GetDirectoryEntry();
        return de.Properties["DistinguishedName"].Value.ToString();
    }

Open in new window


Also try to debug the web service method and see what it returns. If you use the last code from my last post you should get an error it will return it as auto complete.

I don't think that the port number is necessary unless you configured the domain like so.

Regards,
Mishu
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
@Mishu007,

Ok, I'm at the office now and I still get the same stupid JavaScript popup error message. Please see my Markup and Webservice code below.

Markup:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js"></script>  
	<script type="text/javascript">
	    $(function () {
	        $("#<%=tbAuto.ClientID %>").autocomplete({
	            source: function (request, response) {
	                $.ajax({
	                    url: "ADS.asmx/GetADUsers",
	                    data: "{ 'term': '" + request.term + "' }",
	                    dataType: "json",
	                    type: "POST",
	                    contentType: "application/json; charset=utf-8",
	                    dataFilter: function (data) { return data; },
	                    success: function (data) {
	                        response($.map(data.d, function (item) {
	                            return {
	                                value: item
	                            }
	                        }))
	                    },
	                    error: function (XMLHttpRequest, textStatus, errorThrown) {
	                        alert(textStatus);
	                    }
	                });
	            },
	            minLength: 2
	        });
	    });
	</script>
</head>
<body>
    <form id="form1" runat="server">
        <div class="ui-widget">
            <label for="tbAuto">Enter Email: </label>
             <asp:TextBox ID="tbAuto" class="tb" runat="server">
             </asp:TextBox>
        </div>
    </form>
</body>
</html>

Open in new window


Webservice:
using System.Collections.Generic;
using System.Linq;
using System.Web.Services;
using System.Web.Script.Services;
using System.DirectoryServices.ActiveDirectory;
using System.DirectoryServices;
using System;

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.Web.Script.Services.ScriptService]
    public class ads : System.Web.Services.WebService
    {
        [WebMethod]
        public static string GetDomainDN(string domain)
        {
            DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
            Domain d = Domain.GetDomain(context);
            DirectoryEntry de = d.GetDirectoryEntry();
            return de.Properties["DistinguishedName"].Value.ToString();
        }

        [WebMethod]
        public List<string> GetADUsers(string term)
        {
            List<string> res = new List<string>();
            // define a directory searcher for your default context

            try
            {
                string searchRootLDAPPath = GetDomainDN(Domain.GetCurrentDomain().Name);
                using (DirectoryEntry defaultDE = new DirectoryEntry(String.Format("LDAP://{0}", searchRootLDAPPath)))
                {
                    // define searcher - search through entire subtree, search for users 
                    // (objectCategory=Person)           
                    using (DirectorySearcher dsAllUsers = new DirectorySearcher(defaultDE))
                    {
                        dsAllUsers.SearchScope = SearchScope.Subtree;
                        dsAllUsers.Filter = String.Format("(&(objectCategory=person)(objectClass=user)(cn={0}*))", term);

                        // get the results
                        SearchResultCollection result = dsAllUsers.FindAll();

                        foreach (SearchResult searchResult in result)
                        {
                            res.Add(searchResult.GetDirectoryEntry().Name.Remove(0, 3)); //removing the CN=
                        }

                    }
                }
            }
            catch (Exception ex)
            {
                res.Add(String.Format("Error: {0}", ex.Message));
            }

            return res;
        }

    }

Open in new window

0
 
LVL 11

Expert Comment

by:Mihai Stancescu
Comment Utility
Hi,

Can you debug the web service method? I mean does it enter in the method? Maybe it's an AD error.

I've noticed that in the web service the class name is ads and in the jQuery is ADS.asmx.

Also write the correct path in the jquery definition of the web service file in order to work ok.


Regards,
Mishu
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
Mishu007,

Do I need to change the account the app pool runs under from the default IUSR(anonymous) account to a domain user to be able to bind to active directory.  Or is there a way to impersonate the logged in user instead of changing the IUSR account?
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
Hi,

>> Can you debug the web service method? I mean does it enter in the method? Maybe it's an AD error.

Where should I place the breakpoint(s)?

>> I've noticed that in the web service the class name is ads and in the jQuery is ADS.asmx.

You are correct, I saw that to. I removed the ADS.asmx and ADS.cs files and recreated them with the code you supplied but I still get the same error poping up :(

>> Also write the correct path in the jquery definition of the web service file in order to work ok.

Not sure what you mean by that. I have it pointed to url: "ADS.asmx/GetADUsers", now. the index.aspx page is at root level and so is the ADS.asmx page. The code for ADS.asmx is stored in the App_Code directory.
0
 
LVL 4

Author Comment

by:asp_net2
Comment Utility
Hi Mishu007,

Ok, I was able to get it to work. You were correct. I removed the .asmx and .cs and renamed the webservice with "ADS" and it worked fine. You had mentioned that and that was it. I'm going to repubish all markup/code that works.

The only minor thing that I noticed wrong is when I type a character such as "b" it starts the search for all "b's" but if I were to add "bri" during the search it does not recompile what I type it appears to finish the initial search for "b" and then I have to type in "bri" again. Is there a fix for that?

Also, is there a way to speed up the search?
0
 
LVL 11

Expert Comment

by:Mihai Stancescu
Comment Utility
Hi,

You can "trick" that minor problem by using a delay in the options for auto complete, also try setting the minLenght: 2 before the source argument this might also correct this issue.


As for the search to be quicker you can try to cache the results for the searches and use them when ever possible or try to restrict the AD query filter to be more specific. (Ex: limit the search only to a organizational unit inside the AD).


Regards,
Mishu
0
 
LVL 4

Author Closing Comment

by:asp_net2
Comment Utility
Thank you VERY MUCH for ALL your help for seeing this post all the way out. It means ALOT to me. This was something that I have never needed to do before and I can't thank you enough. Is there a reference that you use or used in helping me out with this? If so, could you post the link(s) to me?

Thanks again Mishu007.

Take care...
0
 
LVL 11

Expert Comment

by:Mihai Stancescu
Comment Utility
Hi,

I'm glad I was able to help you.

My links that I've used for reference are these:
This link is what I use when I need to query AD and of course msdn :).
AD in C#
I can't remember exactly which jQuery sites I've looked but I've used something from this one :Aspx jQuery autocomplete

Best of luck...

Regards,
Mishu
0
 

Expert Comment

by:ldap_search ldap_search
Comment Utility
Hi,
@Mihai Stancescu, I'm trying to retrieve a list of all users that exists on ldap, in order to create an autocomplete search box in jquery, but it only search for entire AD when I enter any letter in the search box, I am using PHP to connect to ldap.

any help would much appriciate it

index.php  code:

<!DOCTYPE html>  
 <html>  
      <head>  
           <title>Autocomplete textbox using jQuery, PHP and LDAP</title>  
           <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />  
           <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>  
           <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>  
           <style>  
           ul{  
                background-color:#eee;  
                cursor:pointer;  
           }  
           li{  
                padding:12px;  
           }  
           </style>  
      </head>  
      <body>  
           <br /><br />  
           <div class="container" style="width:500px;" action="ldapSearch.php" method="POST">
                <h3 align="center">Autocomplete textbox using jQuery, PHP and LDAP</h3><br />  
                <label>Enter Name</label>  
                <input type="text" name="Name" id="search-box" class="form-control" placeholder="Enter Name" />  
                <div id="suggesstion-box"></div>  
           </div>  
      </body>  
 </html>  
 <script>  
 $(document).ready(function(){  
      $('#search-box').keyup(function(){  
           var query = $(this).val();  
           if(query != '')  
           {  
                $.ajax({  
                     url:"ldapSearch.php",  
                     method:"POST",  
                     data:{query:query},  
                     success:function(data)  
                     {  
                          $('#suggesstion-box').fadeIn();  
                          $('#suggesstion-box').html(data);  
                     }  
                });  
           }  
      });  
      $(document).on('click', 'li', function(){  
           $('#search-box').val($(this).text());  
           $('#suggesstion-box').fadeOut();  
      });  
 });  
 </script>  

ldapSearch.php code:
<?php
      $server = "";
        $username="";
        $password="";
      $ldapBase = "";
      $ldapConn=ldap_connect($server);
      $r=ldap_bind($ldapConn, $username , $password);
       $filt = "(&(&(&(objectCategory=person)(objectClass=user))))";
        $sr = @ldap_search($ldapConn, $ldapBase, $filt);
        $data = ldap_get_entries($ldapConn, $sr);
        for ($i = 0; $i < $data["count"]; $i++) {
                  if (isset($data[$i]["name"][0]))
  echo "<strong>Name: </strong>" . $data[$i]["name"][0] . "<br />";
 else
 echo "<strong>Name not set</strong><br />";
         }
?>
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Wpf develop 5 30
Please explain: Aspect Oriented Programming 2 51
C# Application Local DB Connection String 23 57
ConsoleSql 1 14
IntroductionWhile developing web applications, a single page might contain many regions and each region might contain many number of controls with the capability to perform  postback. Many times you might need to perform some action on an ASP.NET po…
International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

743 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now