title: Querying Active Directory from MVC result in: Attempted to access an unloaded appdomain. (Exception from HRESULT: 0x80131014)
body: <p>I have an issue using c# on .Net 4 in a MVC web application, where when I query Active Directory, I <em>frequently</em> get an error: <strong><em>Attempted to access an unloaded appdomain. (Exception from HRESULT: 0x80131014).</em></strong></p>
  
  <p>The strange thing is, that it will work flawlessly for a time, and then it will just start happening, and then just disappear again.</p>
  
  <p>I have made a few modifications to the function to get it to work , but they all seem to fail. I am wondering if I am doing something wrong, or if there is a better way to do it.</p>
  
  <p>Here is my current function, that will accept a loginId, and a PrincipalContext. The loginId can either be the user DisplayName <em>i.e "John Smith"</em>, or <em>DOMAINNAME\josmi</em>. The default is to use the first 2 letters of their firstname, and then the first 3 letters of their surname. There is a check in there if this is not the case. This part if fine.</p>
  
  <pre><code>public List&lt;ADGroup&gt; GetMemberGroups(string loginId, PrincipalContext principalContext, int tries = 0)
  {
      var result = new List&lt;ADGroup&gt;();
  
      try
      {
          var samAccountName = "";
          if (loginId.Contains(" "))
          {
              var fName = loginId.Split(Char.Parse(" "))[0].ToLower();
              var sName = loginId.Split(Char.Parse(" "))[1].ToLower();
  
              if (sName.Trim().Length == 2)
                  samAccountName = string.Format("{0}{1}", fName.StartsWith(".") ? fName.Substring(0, 4) : fName.Substring(0, 3), sName.Substring(0, 2));
              else
                  samAccountName = string.Format("{0}{1}", fName.StartsWith(".") ? fName.Substring(0, 3) : fName.Substring(0, 2), sName.Substring(0, 3));
          }
          else
              samAccountName = loginId.Substring(loginId.IndexOf(@"\") + 1);
  
          var authPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, samAccountName);
  
          if (authPrincipal == null)
              throw new Exception(string.Format("authPrincipal is null for loginId - {0}", loginId));
  
          var firstLevelGroups = authPrincipal.GetGroups();
  
          AddGroups(firstLevelGroups, ref result);
      }
      catch
      {
          if (tries &gt; 5)
              throw;
  
          tries += 1;
  
          System.Threading.Thread.Sleep(1000);
          GetMemberGroups(loginId, principalContext, tries);
      }
  
      return result;
  }
  
      private void AddGroups(PrincipalSearchResult&lt;Principal&gt; principal, ref List&lt;ADGroup&gt; returnList)
      {
          foreach (var item in principal)
          {
              if (item.GetGroups().Count() &gt; 0)
                  AddGroups(item.GetGroups(), ref returnList);
  
              returnList.Add(new ADGroup(item.SamAccountName, item.Sid.Value));
          }
      }
  </code></pre>
  
  <p>This function is called like this:</p>
  
  <pre><code>MembershipGroups = ad.GetMemberGroups(user.SamAccountName, new PrincipalContext(ContextType.Domain));
  </code></pre>
  
  <p>The the error that I <em>SOMETIMES</em> get is: </p>
  
  <blockquote>
    <p>System.AppDomainUnloadedException:
    Attempted to access an unloaded
    appdomain. (Exception from HRESULT:
    0x80131014)    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_UserSuppliedServerName()
    at
    System.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.BuildPathFromDN(String
    dn)    at
    System.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.MoveNextPrimaryGroupDN()
    at
    System.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.MoveNext()
    at
    System.DirectoryServices.AccountManagement.FindResultEnumerator<code>1.MoveNext()
    at
    System.DirectoryServices.AccountManagement.FindResultEnumerator</code>1.System.Collections.IEnumerator.MoveNext()</p>
  </blockquote>