Library / SDK
dsbenghe/Novell.Directory.Ldap.NETStandard avatar
dsbenghe/Novell.Directory.Ldap.NETStandard

Novell.Directory.Ldap.NETStandard is a port of a 2000-era Java LDAP client

.NET LDAP client library for .NET Standard >= 2.0, .NET Core >=1.0, NET5/NET6/NET7/NET8 - works with any LDAP protocol compatible directory server (including Microsoft Active Directory).

606 stars157 forksC#MIT

At a glance

What is it?
Novell.Directory.Ldap.NETStandard is an MIT licensed LDAP client for .NET, brought to .NET Standard from Novell's original C# library, which itself came from an OpenLDAP Java project whose first commit is from 2000. It suits a .NET team that needs to talk to Active Directory or any LDAP server, and you should read its ChangeLog before assuming the API matches the Novell docs.
Who is it for?
Novell.Directory.Ldap.NETStandard fits a .NET team that needs LDAP, and cannot use a package that targets only the full .NET Framework, because it is maintained across .NET Standard 2.0 and 2.1, .NET Core, .NET 5 and later, .NET Framework 4.6.1 and upwards, the Universal Windows Platform and Xamarin.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 26 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The code is old, and the documentation says so first

The most useful paragraph in the project documentation is the one explaining where the code came from, because it sets expectations before you install anything.

The library originates with Novell, whose C# LDAP client came from a tool-based conversion of a Java implementation, and that Java project is the OpenLDAP jLDAP repository whose first commit is from 2000. The maintainer says plainly that this explains some of the weirdness in the codebase. The first commit in this repository is the original Novell C# source, and the next twenty or so commits are the port to .NET Standard.

That is an unusual and honest pedigree. A library with twenty years of accumulated edge case handling behind it, and a modern target framework story bolted on top, is a different proposition from a client written recently for modern .NET.

The consequence for you is that the Novell documentation for the original library, available as HTML and as a PDF, still describes much of the API surface, but any behavioural difference introduced by the port has to be found in the ChangeLog that the repository points to.

So the practical reading order is: the README for the shape of the thing, ChangeLog.md for what changed during the port, and the Novell docs for the API detail.

Target frameworks cover everything from .NET Framework to Xamarin

The compatibility story is the main reason this package exists in the .NET ecosystem, and it is broad.

The README describes it as a .NET Standard 2.0 and 2.1 library, compatible with .NET at NET5 and later, .NET Core 2.0 and later, .NET Framework 4.6.1 and later, the Universal Windows Platform and Xamarin, with a link to the .NET Standard support documentation for a more detailed description of supported platforms.

That range matters more than it looks. A library that targets .NET Standard 2.0 can be consumed by essentially every modern .NET target, so a single dependency covers a service on .NET 8, a worker on .NET Core, an older application on .NET Framework 4.6.1 and a Xamarin client without branching. The stated platform support is broad enough that most teams will not have to think about it again.

The project description goes further on the server side, saying it works with any LDAP protocol compatible directory server, including Microsoft Active Directory. That is the claim to check against your own directory, particularly for anything beyond basic bind and search, since LDAP implementations differ in how strictly they follow the specification.

The build badges show two tracks in continuous integration: a maintenance branch at 3.6.x and a developing version on master, both running on Win2019, Linux and MacOS.

Connecting and binding, with async calls and a disposable connection

The sample usage in the README is short enough to read in full, and it shows the shape of the API.

cs
await using (var cn = new LdapConnection())
{
	// connect
	await cn.ConnectAsync("<<hostname>>", 389);
	// bind with an username and password
	// this how you can verify the password of an user
	await cn.BindAsync("<<userdn>>", "<<userpassword>>");
	// call ldap op
	// await cn.DeleteAsync("<<userdn>>")
	// await cn.AddAsync(<<ldapEntryInstance>>)
}

Three things stand out. The connection is disposable, so the await using block closes it when the scope ends, and the pattern suits a method that connects, does one job and releases the session. The operations are async, with ConnectAsync and BindAsync returning tasks. And the bind is a simple username and password bind, with a comment in the sample noting that this is how you verify a user's password, which is the operation behind any password checking feature in a product built on this.

The commented lines show the shape of the write operations, DeleteAsync taking a distinguished name and AddAsync taking an entry instance. Beyond these calls, the API surface follows the Novell original, so expect the naming and structure of a library from the early 2000s rather than a modern async-first design.

Functional tests run against OpenDJ, stress tests against OpenLDAP

The testing story is described in one paragraph of the project documentation and it is more interesting than a coverage percentage would be.

There are a number of functional tests that run against OpenDJ on Ubuntu during CI. Those same functional tests are also run as stress tests, running on multiple threads, against OpenLDAP on Ubuntu. So the suite exercises two different server implementations, and the multithreaded variant exists to surface concurrency problems in a client that keeps a lot of long lived state.

The repository layout backs this up. There are configure-opendj.sh and configure-openldap.sh scripts, an opendj-docker-env.props file, run-opendj.bat for Windows, a stress-tests-matrix.yml, and a test directory. Two directory servers configured in CI, with a stress matrix on top, is a fairly serious piece of test infrastructure for a port that started as a code conversion.

For an adopter, the useful implication is that the CI setup is reproducible. If you need to run the suite locally to check behaviour against your own directory, the scripts in the repository are the starting point rather than something you have to invent.

The build itself is orchestrated by the Azure Pipelines definitions referenced in the badges, with build.sh, build.cmd and build.ps1 present at the root alongside a build directory, plus an appveyor.yml for the older service.

The original samples are kept but excluded from the solution

There is a folder named original_samples, and the project documentation explains its status precisely: the library has some samples which are not included in the solution and are in the original state, they may or may not compile on.NET Standard, but they should be compilable with minimal work.

That sentence is a fair summary of the whole project in miniature. The samples are valuable because they show the API in the shape its original users knew, which is exactly what you need if you are migrating from the Novell library or from code written against the old documentation. They are also a liability as copy-paste material, since they may not build as they are.

So treat them as reference documentation rather than as a tutorial. If you are starting fresh, the short sample in the documentation is the fastest route to a working bind and search, and the original samples are where you look when you want to see how a feature was meant to be used before the port touched it.

The solution file itself, Novell.Directory.Ldap.sln, plus a DotSettings file for Rider and an.editorconfig, indicate the project is developed in Visual Studio and Rider with a shared formatting configuration.

MIT licensing and a release history with a long tail

The licence is MIT, and the repository carries both a LICENSE file and a NOTICE.md. The MIT terms are the permissive ones, so this library can be used inside a proprietary product without copyleft obligations and without a source release requirement.

The release history is where the port shows. The listed releases are 4.0.0 on 2025-03-12, preceded by 4.0.0-beta6 on 2024-07-07 and 4.0.0-beta5 on 2024-04-06. The beta sequence ran for well over a year before the stable tag, which fits a rewrite of the target framework story rather than a routine feature release.

The README also distinguishes the stable package from the pre-release one in its badges: the developing version is published to NuGet as a pre-release from the master branch, while the maintenance version comes from the 3.6.x branch. That is a deliberate two channel setup, and it tells you something about the maintainer's posture: master is where the port to current .NET continues, and 3.6.x is kept stable for consumers who do not want to move.

For a team picking a version today, the choice is between the 4.0.0 stable release for the modern target frameworks and the maintenance line if you are still anchored to the older branch. The repository is not archived and the last push was on 2026-09-26, so work is still landing on master, and the ChangeLog is the place to see exactly what changed between the lines.

Editorial conclusion

Novell.Directory.Ldap.NETStandard fits a .NET team that needs LDAP, and cannot use a package that targets only the full .NET Framework, because it is maintained across .NET Standard 2.0 and 2.1, .NET Core, .NET 5 and later, .NET Framework 4.6.1 and upwards, the Universal Windows Platform and Xamarin. It does not fit a project that wants a modern, purpose-built LDAP API with generated models and strong typing throughout, since the surface is a port of a converted Java codebase and the documentation warns that samples may not compile as they stand. Before adopting it, read ChangeLog.md for the port history and the API differences, confirm the package version you take is the stable 4.0.0 rather than a pre-release, and check the sample usage pattern for how your directory server handles the bind and operation calls you need.

Frequently asked questions

Which .NET versions does Novell.Directory.Ldap.NETStandard support?

It targets .NET Standard 2.0 and 2.1 and is compatible with .NET 5 and later, .NET Core 2.0 and later, .NET Framework 4.6.1 and later, the Universal Windows Platform and Xamarin.

How do I connect and bind with Novell.Directory.Ldap.NETStandard?

Create an LdapConnection inside an await using block, call ConnectAsync with the hostname and port, then BindAsync with a distinguished name and password. The README notes that a simple bind is how you verify a user's password.

Does this LDAP library work with Microsoft Active Directory?

The project description states that it works with any LDAP protocol compatible directory server, including Microsoft Active Directory. The functional test suite runs against OpenDJ in CI, with the same tests also run as multithreaded stress tests against OpenLDAP.

Where did the Novell LDAP client code come from?

It came from Novell, whose C# implementation was a tool-based conversion of a Java project, the OpenLDAP jLDAP repository whose first commit is from 2000. The first commit in this repository is the original Novell C# source, and the port to .NET Standard followed in roughly twenty further commits.

Official sources

  1. dsbenghe/Novell.Directory.Ldap.NETStandard on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dsbenghe-novell-directory-ldap-netstandard.svg)](https://hysenlabs.com/projects/dsbenghe-novell-directory-ldap-netstandard)

Was this useful?