Background
We have an asp.net 4.0 web application written in C # that calls a .net 3.5 web service written in C #. The user ID is transmitted to the web service and returns a list of data depending on the groups of active directories to which the user belongs.
The web service uses the .net 3.5 version of System.DirectoryServices.AccountManagement to obtain the Sids of the groups to which the user belongs.
The call to UserPrincipal.GetGroups is interrupted with the error below. Between the meetings there were very long periods of time, but when this happened, it was repeated for several minutes. This issue has occurred for different AD users.
The stack trace of this exception made no sense to us. We spent a lot of time analyzing Microsoft AD code in Reflector / ILSpy, but could not go beyond the call to IADsPathName.Retrieve.
An exception
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)
Code to play
Please note that the CauseNotSupportedException method imitates code that does not work in our application, but in code somewhere else in the environment in which we do not control.
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 implementation to simulate HttpResponseStream behavior
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) { } }
Questions
- If you run the example above, an error that occurs in the CauseNotSupportedException method is raised in a GetGroups call. How can it be? Any theories or further understanding will be appreciated.
- Any suggestions for further study?
- Any better suggestions than the trick of exception and retry? This is our current job.
Thanks.
Explanation
I'm not sure how much I was in my explanation, so here are some clarifications. Firstly, I am pleased with the active directory that Sids receives. It does what I want it to be done, and I don't think the problem is with this as such. The real problem is that when an error occurs in another unrelated code (this is not in our application), the error manifests itself in a call to GetGroups, therefore, a strange stack trace with the error that originally occurred in System.Web.HttpResponseStream.get_Position (). In the sample application, a NotSupportedException occurs in CauseNotSupportedException, but the code does not break there, it is interrupted when GetGroups is called. If you comment on CauseNotSupportedException () in the sample application, an error never occurs.
I don’t understand how this can happen.