Referral Error when querying

Dec 13, 2011 at 9:25 PM
Edited Dec 13, 2011 at 9:25 PM

Hi MH, I've been trying to use your awesome API here but am having some trouble, anytime I run a query I get:

 

Search request returned 'Referral' with message '0000202B: RefErr: DSID-031007EF, data 0, 1 access points

 

According to MSDN it occurs when the object exists in the directory but it doesn't necessarily list on the current domain controller, it sends a referral back and other stuff (http://technet.microsoft.com/en-us/library/cc978014.aspx). I am using standard Active Directory and it has 4 domain controllers.. I tried putting each of the 4 domain controllers as the server name when configuring the factory, but that didn't get rid of the error. I am able to do the following query in standard AD code with no problem:

 

DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://my.domain.com/DC=my,DC=domain,DC=com")
DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry);

directorySearcher.Filter = "(&(objectCategory=Person)(department=DepartmentA))";

SearchResultCollection collectionResults = directorySearcher.FindAll();

 

This works fine and I am able to iterate through the results. With your API I am doing the following:

Class and map:

 

    public class User
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Department { get; set; }
        public string TelephoneNumber { get; set; }
        public string Address { get; set; }
        public string Title { get; set; }
        public string DistinguishedName { get; set; }
        //public string[] Groups { get; set; }
    }

  public class UserClassMap : ClassMap<User>
    {
        public UserClassMap()
        {
            NamingContext(LdapConnectionConfiguration.UserPath);
            ObjectCategory("Person");
            DistinguishedName(x => x.DistinguishedName);
            Map(x => x.FirstName).Named("givenname");
            Map(x => x.LastName).Named("sn");
            Map(x => x.Department).Named("department");
            Map(x => x.Address).Named("postaladdress");
            Map(x => x.Id).Named("objectguid").StoreGenerated();
            Map(x => x.TelephoneNumber).Named("telephoneNumber");
            Map(x => x.Title).Named("title");
            //Map(x => x.Groups).Named("memberof");
        }
        

    }

And then set the config up I have a helper class (since all of this is so far in a class library):

  public static class LdapConnectionConfiguration
    {
        public static string UserPath { get; set; }
        //public static string GroupPath { get; set; }

        static LdapConnectionConfiguration()
        {
            UserPath = Constants.LdapConnectionStrings.Domain1;
            //GroupPath = "";
        }

        public static void ApplyConfiguration()
        {
            LdapConfiguration config = new LdapConfiguration().AddMapping(new UserClassMap());
            config.ConfigureFactory("my.domain.com");

        }
    }

And in the actual MVC App I have this in the applicationStart():

 

LdapConnectionConfiguration.ApplyConfiguration();

 

And finally in the actual controller I have this:

 

LinqToLdap.DirectoryContext context = new LinqToLdap.DirectoryContext();
List<User> users = context.Query<User>().Where(x => x.Department == "Department A").ToList<User>();

 

And on the second line is where I get that error. Did I configure something wrong? If not, do you know a way around this?

Thanks!

Dec 14, 2011 at 1:45 PM
Edited Dec 14, 2011 at 2:39 PM

Well I think I found out why that was occurring, but now I have a new error. The LDAP string actually refers to a more specific area, I found this out by looking at the AD path of the returned object in the normal query, before my constant for the naming context of the user object was just:

 

LDAP://my.domain.com/DC=my,DC=domain,DC=com

 

But I changed it to:

 

LDAP://my.domain.com/OU=People,DC=my,DC=domain,DC=com

 

Which was where the objects were actually stored, so I guess that is why there was a referral. But now the new error I get is:

 

System.DirectoryServices.Protocols.DirectoryOperationException: The object does not exist.

But the object certainly does or should exist since I can query it normally via the above code. I also tried the same thing with a dynamic query:

 

using (LinqToLdap.DirectoryContext context = new LinqToLdap.DirectoryContext(new LdapConnection("my.domain.com") { Credential = new System.Net.NetworkCredential("xxx", "xxx") }))
            {
                var expression = PredicateBuilder.Create<IDirectoryAttributes>();
                expression = expression.And(da => LinqToLdap.Filter.Equal(da, "department", "DepartmentA"));
                users = context.Query("LDAP://my.domain.com/OU=People,DC=my,DC=domain,DC=com", objectClass: "person")
               .Where(expression)
               .Select(da => new User{ FirstName = da.GetString("givenname"), LastName = da.GetString("sn")})
               .ToList();
            }

Same error, same error also if I try other filters, with or without network credentials, etc. Really at a loss here.

 

Any idea?

Coordinator
Dec 16, 2011 at 3:26 AM

Hi sah,

LINQ to LDAP issues a page request by default to prevent size limit errors.  Paging and referral chasing do not play well together.  You don't get that error with DirectorySearcher because it doesn't support paging.  If you are using version 2.0.2, try using a SearchOptionsControl like so:

 

LinqToLdap.DirectoryContext context = new LinqToLdap.DirectoryContext();
List<User> users = context.Query<User>()
     .Where(x => x.Department == "Department A")
     .WithControls(new DirectoryControl[] {new SearchOptionsControl(SearchOption.DomainScope)})
     .ToList<User>();

 

As for your second error, you're getting "The object does not exist" because "LDAP://my.domain.com/OU=People,DC=my,DC=domain,DC=com" is an invalid naming context.  The domain has already been specified by the connection so you only need specify "OU=People,DC=my,DC=domain,DC=com".

Please let me know if using the SearchOptionsControl works.

Dec 19, 2011 at 4:46 PM

Ah duh, silly me, excellent this is working now! Love this API!