We've implemented a Membership Provider that authenticates to Active Directory and it's using System.DirectoryServices. While using this Membership Provider in an ASP.Net MVC 3 application on Visual Studio 2010 with webdev server we sometimes (1 out of 6 times) get an exception when logging in the application.
System.IO.FileNotFoundException: Could not load file or assembly 'System.Web' or one of its dependencies. The system cannot find the file specified. File name: 'System.Web' at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.LoadWithPartialNameInternal(AssemblyName an, Evidence securityEvidence, StackCrawlMark& stackMark) at System.DirectoryServices.AccountManagement.UnsafeNativeMethods.IADsPathname.Retrieve(Int32 lnFormatType) at System.DirectoryServices.AccountManagement.ADStoreCtx.LoadDomainInfo() at System.DirectoryServices.AccountManagement.ADStoreCtx.get_DnsDomainName() at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOfAZ(Principal p) at System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroupsHelper() at System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroups() === Pre-bind state information === LOG: DisplayName = System.Web (Partial) WRN: Partial binding information was supplied for an assembly: WRN: Assembly Name: System.Web | Domain ID: 2 WRN: A partial bind occurs when only part of the assembly display name is provided. WRN: This might result in the binder loading an incorrect assembly. WRN: It is recommended to provide a fully specified textual identity for the assembly, WRN: that consists of the simple name, version, culture, and public key token. WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue. Calling assembly : HibernatingRhinos.Profiler.Appender, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0774796e73ebf640.
The calling assembly was HibernatingRhinos.Profiler.Appender so after disabling the profiler in log4net config we got to the real exception:
System.AppDomainUnloadedException: Attempted to access an unloaded appdomain. (Except at System.StubHelpers.StubHelpers.InternalGetCOMHRExceptionObject(Int32 hr, IntPtr pCPCMD, Object pThis) at System.StubHelpers.StubHelpers.GetCOMHRExceptionObject(Int32 hr, IntPtr pCPCMD, Object pThis) at System.DirectoryServices.AccountManagement.UnsafeNativeMethods.IADsPathname.Retrieve(Int32 lnFormatType) at System.DirectoryServices.AccountManagement.ADStoreCtx.LoadDomainInfo() at System.DirectoryServices.AccountManagement.ADStoreCtx.get_DnsDomainName() at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOfAZ(Principal p) at System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroupsHelper() at System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroups()
The exception is always thrown at the same method, but for now we are not able to reproduce it as it happens randomly, but approximately 1 out of 6 times. We do however not get the exception when using IIs instead of the built-in Visual Studio 2010 web server.
It probably has something to do with racing conditions when using multiple appdomains in the context of Visual Studio webdev, but that's just guessing. We would really like to know what's the cause of the problem as we don't want to have these exceptions in a production environment.
We found 2 similar cases but no one has found a real solution:
http://our.umbraco.org/forum/developers/extending-umbraco/19581-Problem-with-custom-membership-and-role-provider
http://forums.asp.net/t/1556949.aspx/1
Update 18-05-2011
The smallest amount of code (in asp.net mvc) to reproduce the exception, where userName is your Active Directory loginname.
using System.DirectoryServices.AccountManagement; using System.Web.Mvc; namespace ADBug.Controllers { public class HomeController : Controller { public ActionResult Index() { string userName = "nickvane"; var principalContext = new PrincipalContext(ContextType.Domain); UserPrincipal userPrincipal = UserPrincipal.FindByIdentity( principalContext, IdentityType.SamAccountName, userName); if (userPrincipal != null) { PrincipalSearchResult<Principal> list = userPrincipal.GetAuthorizationGroups(); } return View(); } } }
Alas, the exception still happens at random, so no fully reproducable bug.
Here is what works for me (.Net 4):
Instead of this:
principalContext = new PrincipalContext(ContextType.Domain)
create the principal context with the domain string as well:
E.g.
principalContext = new PrincipalContext(ContextType.Domain,"MYDOMAIN")
It should be fixed in 4.5. See comment, hasn't been fixed yet, but adding the second argument still works as workaround.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With