I have a class that have three methods that have functionalities on Active Directory. Here is the class:
[Export(typeof(IAuthentication))]
public class Authentication : IAuthentication
{
public bool Authenticate(string domain, string username, string password)
{
try
{
using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domain, string.Empty))
{
return principalContext.ValidateCredentials(
username,
password,
ContextOptions.SimpleBind);
}
}
catch (Exception ex)
{
throw ex;
}
}
public UserPrincipal GetUserDetails(string domain, string username)
{
try
{
using (PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domain))
{
return UserPrincipal.FindByIdentity(principalContext, username);
}
}
catch (Exception ex)
{
throw ex;
}
}
public PrincipalSearchResult<Principal> SearchUsers(string domain, string firstName, string lastName, string userName)
{
try
{
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain))
{
UserPrincipal user = new UserPrincipal(ctx);
user.Enabled = true;
user.Name = firstName + "* " + lastName + "*";
user.SamAccountName = userName + "*";
PrincipalSearcher principalSearcher = new PrincipalSearcher();
principalSearcher.QueryFilter = user;
return principalSearcher.FindAll();
}
}
catch (Exception ex)
{
throw ex;
}
}
}
As you see in the class attribute, I’m using this class library as a MEF plugin. In my asp.net mvc 3 application, I call the method like this:
PrincipalSearchResult<Principal> results = _authentication.SearchUsers(
ConfigurationManager.AppSettings["DomainName"],
model.UserSearchCriteria.FirstName,
model.UserSearchCriteria.LastName,
model.UserSearchCriteria.Username);
But after I intend to use the return value of the method, I’m getting Cannot access a disposed object, Object name: ‘PrincipalContext’ exception. I know I’m disposing the PrincipalContext object but if I do not, the connection to the Active Directory will stay open. I think the design of my class is not correct. How can I make it work in a cool way?
I would imagine that when you eventually enumerate over the instance of
PrincipalSearchResult<T>, this deferred operation is trying to access the context, which has since been closed. In this scenario, it is likely better for you to enumerate over the results straight away and return them as domain-specific models. I.e, do the work at the time, and not defer it through returningPrincipalSearchResult<T>.