0
votes

Is there any way to do a search for all records that do NOT match using PrincipalSearcher. Using DirectorySearcher you can apply a filter like (!sn="\*Jay\*"). In other words, all records where the surname does NOT contain the sequence "Jay" anywhere in it. I was wondering if there was anyway to do this with the UserPrincipal parameters.

2

2 Answers

0
votes

Unfortunately this is not an option. I've spent considerable time trying to find a way to easily/efficiently do more advanced searches. The closest you can get to an advanced search is with some of the date options, but nothing for text searching.

What I've ended up doing is running a DirectorySearcher separately using an LDAP query. The only attribute I return from the search (to minimize the result set size and improve speed) is the DN and object type (if the object type is not already filtered on). I then create a new Principal object of the appropriate type using the DN and add it to a collection.

The whole AccountManagement library was designed with a remarkably small set of tasks in mind (apparently), and is very hard to extend. I've pretty much dropped back to using DirectoryServices for most tasks as it is the real library that should be used.

0
votes

I always seem to be answering old questions, but this kept coming up in a search and I believe I've figured this out. In case it helps someone that finds it, here is what I've managed to piece together.

What you want to do is to create a custom AdvancedFilter and create some custom search rules for your needs. The default ones are fairly limited, but you can create just about anything you need.

An example for your question could be handled like this

public class MyAdvancedFilter : AdvancedFilters
{
    public MyAdvancedFilter(Principal principal) : base(principal)
    {

    }

    public void WhereLastName(string lastName, MatchType match)
    {
        // The * is the normal wildcard for LDAP.
        // Remove *'s for an exact match, or create a parameter to choose what to do.
        this.AdvancedFilterSet("sn", "*" + lastName + "*", typeof(string), match);
    }
}

In order to use this, you must also have a custom UserPrincipal object that implements this.

[DirectoryObjectClass("user")]
[DirectoryRdnPrefix("CN")]
public class MyUser : UserPrincipal
{
    public MyUser(PrincipalContext context) : base(context)
    {

    }

    private MyAdvancedFilter searchFilter;
    // use custom search filters
    public new MyAdvancedFilter AdvancedSearchFilter
    {
        get
        {
            if (searchFilter == null)
                searchFilter = new MyAdvancedFilter(this);

            return searchFilter;
        }
    }
}

Now you're ready to use this code.

MyUser u = new MyUser();
// find users without the last name containing "Jay"
u.AdvancedSearchFilter.WhereLastName("Jay", MatchType.NotEquals);

PrincipalSearcher ps = new PrincipalSearcher(u);
var res = ps.FindAll().Cast<MyUser>();

foreach (MyUser p in res)
{
    // use the results here.
}

Hope it helps someone.