Error when performing simple query

May 22, 2012 at 9:02 PM
Edited May 22, 2012 at 9:22 PM

When I execute what seems to be a simple "select all users" query against Active Directory, I'm getting a DirectoryOperationException.

Here's my code:

using (var context = new DirectoryContext(connectionFactory.GetConnection(), true, configuration))
{
    context.Log = new StreamWriter("error.txt");

    users = context.Query<ActiveDirectoryUserEntry>().ToList();
}

I captured the log and I get:

Expression: value(LinqToLdap.DirectoryQuery`1[NAMESPACE.DirectoryServices.ActiveDirectoryUserEntry])
Search Request >
Filter: (objectClass=User)
Attributes: distinguishedname, cn, name, description, objectguid, whenCreated, whenChanged, employeeID, sAMAccountName, givenname, sn, displayName, title, department, company, mail, userPrincipalName, homeDrive, homeDirectory, domain, telephoneNumber, userAccountControl, objectSid, memberOf
Naming Context: OU=Domain Users,DC=SUBDOMAIN,DC=DOMAIN,DC=DOMAIN
Scope: Subtree
Types Only: False
Controls: 
Page Size: 500
Page Cookie Length: 0
Page Control Is Critical: True
Page Control OID: 1.2.840.113556.1.4.319


Search Request >
Filter: (objectClass=User)
Attributes: distinguishedname, cn, name, description, objectguid, whenCreated, whenChanged, employeeID, sAMAccountName, givenname, sn, displayName, title, department, company, mail, userPrincipalName, homeDrive, homeDirectory, domain, telephoneNumber, userAccountControl, objectSid, memberOf
Naming Context: OU=Domain Users,DC=SUBDOMAIN,DC=DOMAIN,DC=DOMAIN
Scope: Subtree
Types Only: False
Controls: 
Page Size: 500
Page Cookie Length: 348
Page Control Is Critical: True
Page Control OID: 1.2.840.113556.1.4.319


Response={ }    Message=The server does not support the control. The control is critical.       Data=...        InnerException={ }      TargetSite={ }  StackTrace=   at System.DirectoryServices.Protocols.LdapConnection.ConstructResponse(Int32 messageId, LdapOperation operation, ResultAll resultType, TimeSpan requestTimeOut, Boolean exceptionOnTimeOut)
   at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
   at LinqToLdap.QueryCommands.StandardQueryCommand.HandleStandardRequest(DirectoryConnection connection, ILinqToLdapLogger log, Int32 maxSize) in C:\Users\ahatter\Documents\Visual Studio 2010\Projects\linqtoldap\Trunk\LinqToLdap\QueryCommands\StandardQueryCommand.cs:line 80
   at LinqToLdap.QueryCommands.StandardQueryCommand.Execute(DirectoryConnection connection, SearchScope scope, Int32 maxPageSize, ILinqToLdapLogger log, String namingContext) in C:\Users\ahatter\Documents\Visual Studio 2010\Projects\linqtoldap\Trunk\LinqToLdap\QueryCommands\StandardQueryCommand.cs:line 45
   at LinqToLdap.DirectoryQueryProvider.Execute(Expression expression) in C:\Users\ahatter\Documents\Visual Studio 2010\Projects\linqtoldap\Trunk\LinqToLdap\DirectoryQueryProvider.cs:line 67      HelpLink=null   Source=System.DirectoryServices.Protocols       HResult=-2146233088
Expression: value(LinqToLdap.DirectoryQuery`1[NAMESPACE.DirectoryServices.ActiveDirectoryUserEntry])
Search Request >
Filter: (objectClass=User)
Attributes: distinguishedname, cn, name, description, objectguid, whenCreated, whenChanged, employeeID, sAMAccountName, givenname, sn, displayName, title, department, company, mail, userPrincipalName, homeDrive, homeDirectory, domain, telephoneNumber, userAccountControl, objectSid, memberOf
Naming Context: OU=Domain Users,DC=SUBDOMAIN,DC=DOMAIN,DC=DOMAIN
Scope: Subtree
Types Only: False
Controls: 
Page Size: 500
Page Cookie Length: 0
Page Control Is Critical: True
Page Control OID: 1.2.840.113556.1.4.319

I rewrote the code to do the paging manually with a while loop and it seems to be erroring once it gets past the first page.

Any idea what I'm doing wrong? I'm trying to grab all of the users in an OU (which is mapped with the object and context).

Coordinator
May 24, 2012 at 10:58 PM

Hi Jay,

Can you tell me which version of Active Directory you are using?  For whatever reason your directory is not allowing you to continue paging.  My guess is that referral chasing might be causing the problem.  Try adding this before ToList:

.WithControls(new [] { new SearchOptionsControl(SearchOption.DomainScope) } )

 

 

May 25, 2012 at 5:17 PM

I ran DS query and we are on Windows 2008 AD (object version 44).

I ran the "with controls" modification and got the same errors. Any other things I can check?

Thanks for your help so far!

Coordinator
May 27, 2012 at 8:32 PM

On the connection factory, can you try setting the protocol version to 3?

Jun 19, 2012 at 3:24 PM

Hi there, i had the same error when i tried to query "iPlanet directory server". The error cause was the "PageResultRequestControl" which is added by default before the request is sent.

In the current source, there is a posibility to deactivate paging. Maybe that helps you too?

 

When will be the release? :-)

 

Coordinator
Jun 21, 2012 at 3:13 AM

Unfortunately "soon" is the best answer I can give :)

Jun 22, 2012 at 10:45 PM

I actually tried the protocol version first (found it on another site).

I've compiled 3.0 and am trying to implement the disable paging config (since my result set is likely in the thousands). In order to get my class map's working I need to implement ClassMap<T>.PerformMapping

I realize that this is pre-release code, that you are still working on it, etc. But can you give me any example code? I'm guessing that you are moving the mapping information from the constructor to this method.

I really think this project is unbelievably fantastic and that you've produced an immensely useful tool. Thank you for your helping us all wrestle with LDAP.


Coordinator
Jun 23, 2012 at 2:16 AM
Edited Jun 23, 2012 at 2:18 AM

Not a problem.  I knew next to nothing about LDAP when I started this project so I'm just glad it's useful.

OK, so first, PerformMapping exists for developers that want to map their classes, but want to perform a "late" naming context mapping.  When you add the mapping to the LdapConfiguration you can optionally pass in the naming context, object category, and object classes.  If you don't plan on doing that then your mapping can just ignore what's passed in.

public override IClassMap PerformMapping(string namingContext = null, 
                                         string objectCategory = null, 
                                         bool includeObjectCategory = true, 
                                         IEnumerable<string> objectClasses = null, 
                                         bool includeObjectClasses = true)
{
// ignore the passed in object category and just set it here
 ObjectCategory("user");
// take the passed in naming context if it's available
 NamingContext(namingContext ?? "naming context"); DistinguishedName(c => c.DistinguishedName); Map(c => c.Cn) .ReadOnly(); Map(c => c.ObjectGuid) .StoreGenerated(); return this; }

Second, can you call ListServerAttributes and tell me if 1.2.840.113556.1.4.319 is in the list of supported controls?

And third, can you try manual paging like the example here (page size of 1000) using WithControls and set the PageResultRequestControl.IsCritical property to false each time?  I've seen a few references to directories returning an error if the request can be satisfied without the control, but the control is marked critical.

Jul 3, 2012 at 2:33 PM
Edited Jul 3, 2012 at 2:34 PM

Okay. Succesfully implemented mapping (I just did a

return this;

in the required implmentation and kept my constructor mapping. I checked the ListServerAttributes (just looked at one of my search requests in a debug) and I have:

Controls: 
Page Size: 1000
Page Control Is Critical: False
Page Control OID: 1.2.840.113556.1.4.319

and I implemented the manual paging like:

//start paging
var page = context.Query<ActiveDirectoryUserEntry>()
    .Where(u => u.MemberOf.Contains(group))
    .Select(u => u)
    .WithControls(new[] { new PageResultRequestControl(1000) { IsCritical = false } })
    .ToList() as LdapPage<ActiveDirectoryUserEntry>;
                
users.AddRange(page);

//go to next page
while (page.HasNextPage)
{
    page = context.Query<ActiveDirectoryUserEntry>()
                .Where(u => u.MemberOf.Contains(group))
    .Select(u => u)
.WithControls( new[] { new PageResultRequestControl(1000) { Cookie = page.NextPage, IsCritical = false } }) .ToList() as LdapPage<ActiveDirectoryUserEntry>; users.AddRange(page); }

and I got a DIFFERENT error (progess!)

System.DirectoryServices.Protocols.DirectoryOperationException: An operation error occurred.
    at System.DirectoryServices.Protocols.LdapConnection.ConstructResponse(Int32 messageId, LdapOperation operation, ResultAll resultType, TimeSpan requestTimeOut, Boolean exceptionOnTimeOut)
   at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
   at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request)
   at LinqToLdap.QueryCommands.StandardQueryCommand.HandlePagedRequest(DirectoryConnection connection, PageResultRequestControl pageRequest, ILinqToLdapLogger log)
   at LinqToLdap.QueryCommands.StandardQueryCommand.Execute(DirectoryConnection connection, SearchScope scope, Int32 maxPageSize, Boolean pagingEnabled, ILinqToLdapLogger log, String namingContext)
   at LinqToLdap.DirectoryQueryProvider.Execute(Expression expression)
   at LinqToLdap.QueryProvider.Execute(Expression expression)
   at LinqToLdap.QueryableExtensions.ToList(IQueryable`1 source)

I'm stepping through the debugger and googling so if I find out more I'll try to post it here.