5

I'm using the code below to look up information in active directory when a user logs on to a website. Running against a local domain it's very quick, but running over a VPN to a remote trusted domain, it's very slow (takes around 7 or 8 seconds). Running dsa.msc from the same box to the remote domain is almost as quick as running it locally.

I'm using property filtering to retrieve the minimum amount of data possible, so is there something inherently slow about System.DirectoryServices in this scenario, or does anyone have any hints on how to improve the performance?

The network connection across the VPN is fine, it's only this code that runs slowly.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var LDAPConnection = new DirectoryEntry("LDAP://domain/dc=domain,dc=com", "username", "password"))
            {
                LDAPConnection.AuthenticationType = AuthenticationTypes.Secure;
                using (DirectorySearcher Searcher = new DirectorySearcher(LDAPConnection))
                {
                    Searcher.Filter = "(&(&(objectclass=user)(objectcategory=person))sAMAccountName=username)";
                    Searcher.PropertiesToLoad.Add("mail");

                    SearchResult result = Searcher.FindOne(); //this line takes ages!

                    string EmailAddress = result.Properties["mail"][0].ToString();
                    Console.WriteLine(EmailAddress);
                }
            }
        }
    }
}
makerofthings7
  • 60,103
  • 53
  • 215
  • 448
wefwfwefwe
  • 3,382
  • 1
  • 21
  • 24

2 Answers2

6

Another suggestion is to use System.DirectoryServices.Protocols directly; you code will look like:

string filter = "(&(&(objectclass=user)(objectcategory=person))" + 
                "sAMAccountName=username)";
NetworkCredential credentials = new NetworkCredential(...);
LdapDirectoryIdentifier directoryIdentifier = 
   new LdapDirectoryIdentifier("server", 389, false, false);
using (LdapConnection connection = 
   new LdapConnection(directoryIdentifier, credentials, AuthType.Basic))
{
    connection.Timeout = new TimeSpan(0, 0, 30);
    connection.SessionOptions.ProtocolVersion = 3;
    SearchRequest search = 
        new SearchRequest(query, filter, SearchScope.Base, "mail");
    SearchResponse response = connection.SendRequest(search) as SearchResponse;
    foreach(SearchResultEntry entry in response.Entries)
    {
        Console.WriteLine(entry.Attributes["mail"][0]);
    }
}
Rubens Farias
  • 57,174
  • 8
  • 131
  • 162
  • it turns out that pointing the connection at a specific server made a huge difference, so i'm accepting your answer on the basis that it gave me the hint to try that. cheers. – wefwfwefwe Dec 23 '09 at 14:34
  • 1
    also got a boost from using authenticationtypes.fastbind. – wefwfwefwe Dec 24 '09 at 11:56
  • 3
    Can you give an example as to what the variable "query" should contain? It's not declared in your answer – Sjuul Janssen Feb 15 '13 at 10:43
  • An example that shows the value of `query` can be seen on this question http://stackoverflow.com/questions/13567685/ldapconnection-searchrequest-throws-exception-for-the-size-limit-was-exceeded – Drew Chapin Apr 13 '14 at 05:50
1

I have never tried the scenario you are describing (connecting over VPN to Active Directory) but the line you marked is the line that causes the connection to be opened. You are not connected to the server before calling FindOne. My guess is that establishing the connection lasts 7-8 secs.

If you cannot find exact answer on stackoverflow try this forum: http://directoryprogramming.net/forums/default.aspx (I'm not saying that stackoverflow is not helpful, but I found some answers to my ad/ldap questions on DirectoryProgramming.net forum).

empi
  • 15,755
  • 8
  • 62
  • 78