You can’t get there from here. That seems to be the theme with too many programming interfaces. In particular, the .Net System.DirectoryServices classes are too general purpose such that specific tasks become maddeningly difficult or impossible. I know AD and I know LDAP, but trying to do simple things with .Net is just too difficult.

For example, AD is based on LDAP and x500 which describes a hierarchical object system. Conceptually it is very similar to a file system. AD containers are similar to file system directories. AD objects are similar to file system objects. Yes, this is an oversimplification, but you should be able to do something like CD (change directory) from an AD parent container into a child container. However, there is no CD command in DirectoryServices. Instead, you have two choices: specify the full path to a container to connect to it, or enumerate all of the children of a container and choose one to connect to. The enumeration returns the full path of each child. There is no navigation by relative paths. Worse yet is the complexity of LDAP paths themselves (thanks to x500). It doesn’t need to be this complicated.

This complexity is compounded by the way the .Net System.DirectoryServices classes are implemented. They are just wrappers around the ADSI COM interfaces. ADSI uses IDispatch. This made some sense back in 1998 when ADSI was being designed. At that time Visual Basic was the predominant Microsoft scripting language and IDispatch provided a convenient dynamic typing system. Another decision made at that time was to have ADSI support multiple directory protocols including LDAP and WinNT (and later IIS). Unfortunately this adds a layer of unnecessary complexity to the .Net wrappers due to the fact that there many subtle differences between these and the other supported protocols.

It could have been done differently. A namespace and set of classes could have been designed specifically for doing common AD operations. Those classes could have talked directly to AD using the LDAP wire protocol but at the same time abstracting and simplifying the complexities of LDAP and AD. Instead we are left with multiple layers of interfaces with really no simplification at all. Microsoft did add the System.DirectoryServices.ActiveDirectory namespace classes to address some of the underlying complexities, but only for specific scenarios like managing forests and trusts. Ditto for System.DirectoryServices.Protocols. A simple operation like finding all users that match a set of conditions still requires an understanding of many complex details. How many people understand pre-fix notation and its application to LDAP query filters? Why should people even have to be subjected to such difficulties?

Fortunately there are promising solutions. One is the Active Directory module for PowerShell. The authors did a good job of translating many of the AD/LDAP peculiarities into standard PowerShell syntax. The other is a new API that has been added to the Windows Azure Active Directory. This is being called a Graph API. It is a RESTful web service that references all AD objects using standard URI naming. AD objects become web resources with standard URI resource naming. The attributes on objects that describe relationships to other objects (e.g. group membership, OU containment) are also expressed as URIs. Hence the “graphness” that allows simple traversal based on object relationships. See Kim Cameron’s blog for more graph API info.

In the meantime, accessing AD from .Net remains challenging without resorting to writing lots of code or buying third party libraries.

Advertisements