Reputation: 43
I'm pretty new to active directory and I'm currently working on a library for a project to easily manage our active directory objects like users, resources, groups and so on.
The library is in .NetStandard 2.0 and I use the Principal classes from
System.DirectoryServices.AccountManagement
As the UserPrincipal class doesn't contain all the properties that we could need, I tried to implement an UserPrincipalExtended class that, for now, just add the Initials property.
Here is my class :
[DirectoryObjectClass("user")]
[DirectoryRdnPrefix("CN")]
public class UserPrincipalExtended : UserPrincipal
{
public UserPrincipalExtended(PrincipalContext context) : base(context) { }
public UserPrincipalExtended(PrincipalContext context, string samAccountName, string password, bool enabled) : base(context, samAccountName, password, enabled) { }
[DirectoryProperty("Initials")]
public string Initials
{
get
{
if (ExtensionGet("initials").Length != 1) return null;
return (string)ExtensionGet("initials")[0];
}
set { ExtensionSet("initials", value); }
}
public static new UserPrincipalExtended FindByIdentity(PrincipalContext context, string identityValue)
{
return (UserPrincipalExtended)FindByIdentityWithType(context, typeof(UserPrincipalExtended), identityValue);
}
public static new UserPrincipalExtended FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
{
return (UserPrincipalExtended)FindByIdentityWithType(context, typeof(UserPrincipalExtended), identityType, identityValue);
}
}
When I do a search in the active directory using the UserPrincipal class, it works as expected :
using (var context = _contextProvider.GetPrincipalContext())
using (var query = new UserPrincipal(context))
using (var searcher = new PrincipalSearcher(query))
{
foreach (var principal in searcher.FindAll())
{
UserPrincipal userPrincipal = principal as UserPrincipal;
if (CheckHelper.IsFilled(userPrincipal))
{
Console.WriteLine($"{userPrincipal.StructuralObjectClass} : {userPrincipal.SamAccountName}");
}
}
}
/*Output
user : cadmin
user : Guest
user : DefaultAccount
*/
But if I try to perform the same search using my own class, the result contains also computers :
using (var context = _contextProvider.GetPrincipalContext())
using (var query = new UserPrincipalExtended(context))
using (var searcher = new PrincipalSearcher(query))
{
foreach (var principal in searcher.FindAll())
{
UserPrincipalExtended userPrincipalExtended = principal as UserPrincipalExtended;
if (CheckHelper.IsFilled(userPrincipalExtended))
{
Console.WriteLine($"userPrincipalExtended.StructuralObjectClass} : {userPrincipalExtended.SamAccountName}");
}
}
}
/*Output
user : cadmin
user : Guest
user : DefaultAccount
computer : WS001$
computer : WS002$
computer : WS003$
*/
As my UserPrincipalExtended class has the attribute :
[DirectoryObjectClass("user")]
I thought that was enough to filter on this object type in the active directory, but it seems it does not.
Any idea of what's going on here?
Cheers
Upvotes: 3
Views: 493
Reputation: 36
microsoft Principal types filter creating code
Also faced with this problem.Having rummaged in the source code, I found such a workaround.
[DirectoryObjectClass("user)(objectCategory=user")]
Upvotes: 2
Reputation: 2139
In your constructor you can set the ObjectCategory
attribute to User
[DirectoryObjectClass("user")]
[DirectoryRdnPrefix("CN")]
public class UserPrincipalExtended : UserPrincipal
{
public UserPrincipalExtended(PrincipalContext context) : base(context)
{
// Set ObjectCategory to user so computer objects are not returned
ExtensionSet("objectCategory", "user");
}
[DirectoryProperty("Initials")]
public string Initials
{
get
{
if (ExtensionGet("initials").Length != 1) return null;
return (string)ExtensionGet("initials")[0];
}
set { ExtensionSet("initials", value); }
}
}
Upvotes: 1