У нас есть веб-приложение asp.net 4.0, написанное на C #, которое вызывает веб-службу .net 3.5, написанную на C # . Веб-сервису передается идентификатор пользователя, и он возвращает список данных в зависимости от активных групп каталогов, к которым принадлежит пользователь.
Веб-служба использует версию .net 3.5 System.DirectoryServices.AccountManagement для получения идентификаторов SID групп, к которым принадлежит пользователь.
Вызов UserPrincipal.GetGroups периодически завершается сбоем из-за ошибки, указанной ниже. Между событиями были очень большие промежутки времени, но когда они действительно происходили, они повторялись неоднократно в течение нескольких минут. Проблема возникла для разных пользователей AD.
Трассировка стека этого исключения не имела для нас никакого смысла. Мы потратили много времени на изучение кода Microsoft AD в Reflector / ILSpy, но не смогли выйти за рамки вызова IADsPathName.Retrieve.
System.NotSupportedException: Specified method is not supported.
at System.Web.HttpResponseStream.get_Position()
at System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64 offset, Int32 origin)
at System.DirectoryServices.AccountManagement.UnsafeNativeMethods.IADsPathname.Retrieve(Int32 lnFormatType)
at System.DirectoryServices.AccountManagement.ADStoreCtx.LoadDomainInfo()
at System.DirectoryServices.AccountManagement.ADStoreCtx.get_DnsForestName()
at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOf(Principal p)
at System.DirectoryServices.AccountManagement.Principal.GetGroupsHelper()
at System.DirectoryServices.AccountManagement.Principal.GetGroups()
at Data.SoftwarePublishingItemData.GetSids(String requestedForUserId)
at Data.SoftwarePublishingItemData.GetSoftwarePublishingItems(IDatabaseContext dbContext, GetSoftwarePublishingItemsSettings settings, XBXmlDocument parameters)
at Web.GetSoftwarePublishingItems.GetFlexiFieldData(String xml)
Обратите внимание, что метод CauseNotSupportedException имитирует код, который не выполняется в нашем приложении, а находится в другом месте в среде, которую мы не контролируем.
class Program
{
static void Main(string[] args)
{
CauseNotSupportedException();
string samAccountName = "domain.user";
using (var principalContext = new PrincipalContext(ContextType.Domain))
{
using (var userPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, samAccountName))
{
if (userPrincipal == null)
throw new ActiveDirectoryObjectNotFoundException();
using (var groups = userPrincipal.GetGroups())
{
foreach (GroupPrincipal group in groups)
{
Console.WriteLine(group.Sid);
}
}
}
}
}
public static void CauseNotSupportedException()
{
using (var b = new Bitmap(500, 500, PixelFormat.Format32bppArgb))
{
b.Save(new FakeStream(), ImageFormat.Png);
}
}
}
Реализация Stream для имитации поведения HttpResponseStream
public class FakeStream : Stream
{
public override bool CanRead { get { return false; } }
public override bool CanSeek { get { return false; } }
public override bool CanWrite { get { return true; } }
public override void Flush() { }
public override long Length { get { throw new NotSupportedException("No Seek"); } }
public override long Position
{
get { throw new NotSupportedException("No Seek"); }
set { throw new NotSupportedException("No Seek"); }
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new InvalidOperationException("Write only stream");
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException("net_noseek");
}
public override void SetLength(long value) { }
public override void Write(byte[] buffer, int offset, int count) { }
}
Спасибо.
Разъяснение
Я не уверен, насколько ясно я был в своем объяснении, поэтому вот некоторые пояснения. Во-первых, я доволен кодом активной директории, который получает Sids. Это делает то, что я хочу, и я не думаю, что проблема в этом как таковая. Реальная проблема заключается в том, что когда ошибка возникает в другом несвязанном коде (его нет в нашем приложении), ошибка проявляется в вызове GetGroups, отсюда и странная трассировка стека с ошибкой, изначально возникшей в System.Web.HttpResponseStream.get_Position (). В примере приложения NotSupportedException возникает в CauseNotSupportedException, но код там не прерывается, он прерывается при вызове GetGroups. Если вы закомментируете CauseNotSupportedException () в примере приложения, ошибка никогда не возникнет.
Мне непонятно, как такое могло случиться.