Click here to Skip to main content
Licence CPOL
First Posted 12 Nov 2008
Views 10,472
Downloads 76
Bookmarked 15 times

Typed LDAP Queries

By | 12 Nov 2008 | Article
Dynamically generating well formed LDAP queries using managed code.

Introduction

Writing queries using Lightweight Directory Access Protocol (LDAP) has always been challenging, especially when you are not used to the LDAP syntax. The inclusion of the System.DirectoryServices namespaces in the .NET framework made writing code for LDAP libraries a lot easier than with the traditional Active Directory Services Interfaces (ADSI) in non-managed languages. However, search functions in this namespaces such as the DirectorySearcher class still relies on the ability of the programmer to write LDAP queries properly, thus leaving the fate of a well formatted query on the hands of the runtime.

A More Structured Solution

After analyzing and looking for a more structured way of writing these types of queries, I found a very compelling and clever way of writing function statements with conditional logic, which I found in Microsoft Excel. Excel’s way of writing functions consists of defining the logical operator as the function and the members inside the function on which they operate. For instance, consider the following query:

Select car from cars where (car.color = colors.red OR car.color = colors.blue) 
  AND car.make = makes.ford AND car.passengers > 5 AND car.model >= 2008

It can be also expressed as:

AND(
   OR(
      EQUALTO(car.color, colors.red), 
      EQUALTO(car.color, colors.blue)), 
   EQUALTO(car.make, makes.ford), 
   GREATHERTHAN(car.passengers, 5), 
   OR(
      GREATHERTHAN(car.model, 2008),
      EQUALTO (car.model, 2008))

In LDAP, the query would be as follows:

(&( |((color=red)(color=blue))(make=ford)(passengers>5)(model>=2008) ))

You can see how similar the last two expressions are.

Search Criteria

The first thing we need is a helper class to define expressions using syntax like the above. The SearchCriteria class easily allows to define queries of this type, as defined below:

public class SearchCriteria
{
   public SearchCriteria<T>[] Criteria { get; set; }
   public static AndCriteria And(params SearchCriteria<T>[] criteria)
   public static OrCriteria Or(params SearchCriteria<T>[] criteria)
   public static NotCriteria Not(SearchCriteria<T> criteria)
   public static GreatherThanFunctionCriteria GreatherThan(T name, string value)
   public static LessThanFunctionCriteria LessThan(T name, string value)
   public static EqualToFunctionCriteria EqualTo(T name, string value)
   public static ContainsFunctionCriteria Contains(T name, string value)
   public static IsLikeFunctionCriteria IsLike(T name, string value)
}

Then, to define the car query from the example above, we have to define an enumeration for fields allowed for the element car, as follows:

public enum Car { color, make, passengers, model, } 

Typed LDAP

Here is how we express the query in managed code:

var expression = SearchCriteria<Car>.And( 
   SearchCriteria<Car>.Or( 
      SearchCriteria<Car>.EqualTo(Car.color, Colors.red.ToString()), 
      SearchCriteria<Car>.EqualTo(Car.color, Colors.blue.ToString())), 
   SearchCriteria<Car>.EqualTo(Car.make, Makes.ford.ToString()), 
   SearchCriteria<Car>.GreatherThan(Car.passengers, "5"), 
   SearchCriteria<Car>.Or( 
      SearchCriteria<Car>.GreatherThan(Car.model, "2008"),  
      SearchCriteria<Car>.EqualTo(Car.model, "2008")));

Once we have a criteria object, we can pass that to the LdapBuilder engine, which is another static class with one method:

public static string GetLdap(SearchCriteria criteria)
...
string ldapQuery = LdapBuilder<Car>.GetLdap(expression);

Then, invoking this method will dynamically call the proper routines that will generate a string representing a well formed LDAP query, that simple!

The Sample Code

In the sample code, you will find a fully functional version of this engine along with the implementation of the car example used in this article. Enjoy it :)

TypedLdapTestForm.jpg

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

luis_botero

Software Developer (Senior)

United States United States

Member

Born and built for Software Development. Eager to develop systems that drive business and human intelligence to the next level. Love Artificial Intelligence and have abundant experience in developing systems with a large user base. I know more than just how to write code that compiles. I can produce software that is fast, reliable, well-tested, secure, maintainable, globalizable, and on down the list of attributes of high-quality code.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralLDAP Criteria PinmemberCubaman7:18 19 Nov '08  
GeneralExcellent idea Pinmemberrht3414:19 16 Nov '08  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120517.1 | Last Updated 12 Nov 2008
Article Copyright 2008 by luis_botero
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid