针对 Windows 平台,Microsoft 提供了三个主要目录平台:Active Directory 域服务、每台 Windows 计算机上的本地安全帐户管理器 (SAM) 数据存储,以及比较新的 Active Directory 轻型目录服务或 AD LDS(即您先前已经知道的 Active Directory 应用程序模式或简称 ADAM)。这篇博文不是讲活动目录的使用,具体可以参照MSDN一篇文章专门介绍活动目录的编程http://msdn.microsoft.com/zh-cn/magazine/cc135979.aspx。
本文主要是记录使用GetAuthorizationGroups()接口或用用户的时候经常抛出的一个错误:具体可以看Microsoft Connect http://connect.microsoft.com/VisualStudio/feedback/details/566463/attempted-to-access-an-unloaded-appdomain-exception-from-hresult-0x80131014-when-calling-getauthorizationgroups。
微软并没有给出解决方案,在stackoverflow 上也有讨论到这个问题 http://stackoverflow.com/questions/5895128/attempted-to-access-an-unloaded-appdomain-when-using-system-directoryservices。
在stackoverflow上的讨论中有了一种解决方案,再发生AppDomainUnloadedException 错误的时候,通过休眠一段时间重新调用这个接口:
private PrincipalSearchResult<Principal> GetAuthorizationGroups(UserPrincipal userPrincipal, int tries)
{
try
{
return userPrincipal.GetAuthorizationGroups();
}
catch (FileNotFoundException ex)
{
if (tries > 5)
throw; tries++;
Thread.Sleep(1000);
return GetAuthorizationGroups(userPrincipal, tries);
}
catch (AppDomainUnloadedException ex)
{
if (tries > 5)
throw; tries++;
Thread.Sleep(1000);
return GetAuthorizationGroups(userPrincipal, tries);
}
}
这样就会造成一个问题,如果发生了异常,接口就非常的慢了。这可以通过引入缓存机制来解决:
public override String[] GetRolesForUser(String username)
{
// If SQL Caching is enabled, try to pull a cached value.
if (_EnableSqlCache)
{
String CachedValue;
CachedValue = GetCacheItem('U', username);
if (CachedValue != "*NotCached")
{
return CachedValue.Split(',');
}
}
ArrayList results = new ArrayList();
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, null, _DomainDN))
{
try
{
UserPrincipal p = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
var tries = 0;
var groups = GetAuthorizationGroups(p, tries);
foreach (GroupPrincipal group in groups)
{
if (!_GroupsToIgnore.Contains(group.SamAccountName))
{
if (_IsAdditiveGroupMode)
{
if (_GroupsToUse.Contains(group.SamAccountName))
{
results.Add(group.SamAccountName);
}
}
else
{
results.Add(group.SamAccountName);
}
}
}
}
catch (Exception ex)
{
throw new ProviderException("Unable to query Active Directory.", ex);
}
}
// If SQL Caching is enabled, send value to cache
if (_EnableSqlCache)
{
SetCacheItem('U', username, ArrayListToCSString(results));
}
return results.ToArray(typeof(String)) as String[];
}
上面的代码来自于Active Directory Roles Provider。
本文来自合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号