Antecedentes
de error intermitente extraño Tenemos una aplicación asp.net 4.0 web escrito en C# .NET que llama a un servicio Web 3.5 escrito en C#. El servicio web recibe una identificación de usuario y devuelve una lista de datos en función de los grupos de directorios activos a los que pertenece el usuario.manejo de errores al llamar UserPrinciapl.GetGroups en System.DirectoryServices.AccountManagement
El servicio web .NET utiliza la versión 3.5 de System.DirectoryServices.AccountManagement para obtener los SID de los grupos pertenece el usuario.
La llamada a UserPrincipal.GetGroups falla intermitentemente con el error abajo. Hubo periodos de tiempo muy largos entre las ocurrencias, pero cuando ocurrió, ocurrió repetidamente durante varios minutos. El problema ocurrió para diferentes usuarios de AD.
El seguimiento de pila de esta excepción no tenía sentido para nosotros. Pasamos mucho tiempo mirando el código Microsoft AD en Reflector/ILSpy pero no pudimos ir más allá de la llamada a IADsPathName.Retrieve.
Excepción
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)
Código para reproducir
Tenga en cuenta, el método CauseNotSupportedException está imitando código que no se está ejecutando en nuestra aplicación, pero en el código en otro lugar en el ambiente que no estamos en control de.
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);
}
}
}
Implementación de corriente para imitar HttpResponseStream comportamiento
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) { }
}
Preguntas
- Si ejecuta el ejemplo anterior, el error que se produce en el método CauseNotSupportedException se lanza en el llame a GetGroups. ¿Como puede ser? Se agradecerá cualquier teoría o visión adicional.
- ¿Alguna sugerencia sobre cómo investigar más?
- mejor sugerencias que captura la excepción y volver a intentar? Ese es nuestro trabajo actual alrededor.
Gracias.
Aclaración
No estoy seguro de cómo está claro que he estado en mi explicación así que aquí tiene algunas aclaraciones. En primer lugar, estoy contento con el código de directorio activo que obtiene el Sids. Eso hace lo que quiero que haga y no creo que el problema sea con eso como tal. El verdadero problema es que cuando se produce un error en otro código no relacionado (que no está en nuestra aplicación) el error se manifiesta en las GetGroups llaman, por lo tanto, el seguimiento de pila extraña con el error que se produce inicialmente en System.Web.HttpResponseStream.get_Position(). En la aplicación de muestra NotSupportedException ocurre en CauseNotSupportedException pero el código no se rompe allí, se rompe en la llamada a GetGroups. Si comenta CauseNotSupportedException() en la aplicación de muestra, el error nunca ocurre.
Es claro para mí cómo esto puede suceder.
Pregunta, ¿está tratando de averiguar si los usuarios pertenecen a un grupo en particular o no? Estoy tratando de obtener una mejor comprensión de lo que realmente está buscando. Es posible que tenga una sugerencia sobre un mejor enfoque con respecto a codificación ... aquí hay un enlace que también ayudará a pegar 2 fragmentos de código a continuación que deberían ayudarlo a obtener lo que necesita con mayor facilidad. http://msdn.microsoft.com/en-us/magazine/cc135979.aspx – MethodMan
Muchas gracias por la respuesta. Lo que necesito es una lista de Sids de los grupos de los que un usuario es miembro. Actualmente estoy usando el espacio de nombres System.DirectoryServices.AccountManagement (UserPrincipal.GetGroups está en ese espacio de nombres). Entonces, mi muestra de código es muy similar a la que publicaste a continuación. El código que obtengo es lo que quiero, es solo el error intermitente que se produce por un código no relacionado que intento entender. Si tiene tiempo, valdría la pena ejecutar el código de muestra y recorrerlo. –
ok no es un problema ... fue difícil determinar al principio qué era lo que deseabas ... mis disculpas aún necesitarías verificar esa propiedad o las (cadenas) Propiedades ["samAccountName"] [0] .ToString() porque esto Sería un Objeto en este momento ... Espero que esto tenga sentido. – MethodMan