title: how to get custom role provider with a custom user principal
body: <p>long time lurker first time poster..</p>
  
  <p>trying to implement a simple custom role and membership provider for MVC.</p>
  
  <p>Have implemented the role and membership provider classes and hooked them into my web.config. added code to validate my users against a custom database and it works fine. </p>
  
  <p>However, I dont like the way my roleprovider hits the database on each request so I added some code to try and read this from the authentication ticket as follows:</p>
  
  <p>custom role provider:</p>
  
  <pre class="lang-c# prettyprint-override"><code>public override string[] GetRolesForUser(string username)
     {
         if (HttpContext.Current.User != null)
         {
             return ((UserPrincipal)HttpContext.Current.User).Roles.ToArray();
         }
         else
         {
             UserPrincipal user = orchestrator.GetUserByLoginID(username);
             return user.Roles.ToArray();
         }
     }
  </code></pre>
  
  <p>then I added this code in global.asax to persist the roles and some other useful user info into the cookie using a custom user principal object:</p>
  
  <pre class="lang-c# prettyprint-override"><code>protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
      {
          HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
  
          if (authCookie != null)
          {
              FormsAuthenticationTicket authTicket =      FormsAuthentication.Decrypt(authCookie.Value);
  
              JavaScriptSerializer serializer = new JavaScriptSerializer();
  
              UserPrincipalModel userFromTicket = serializer.Deserialize&lt;UserPrincipalModel&gt;(authTicket.UserData);
  
              UserPrincipal newUser = new UserPrincipal();
              newUser.UserId = userFromTicket.UserId;
              newUser.FullName = userFromTicket.Fullname;
              newUser.Email = userFromTicket.Email;
              newUser.Roles = userFromTicket.Roles;
              newUser.Identity = new GenericIdentity(userFromTicket.Username);
  
              HttpContext.Current.User = newUser;
          }
      }
  </code></pre>
  
  <p>my user principal class:</p>
  
  <pre class="lang-c# prettyprint-override"><code>  public class UserPrincipal : IPrincipal
  {
      public UserPrincipal() { }
      public UserPrincipal(int userId, string userName, string fullName, string password)
      {
          UserId = userId;
          UserName = userName;
          FullName = fullName;
          Password = password;
      }
      public virtual int UserId { get; set; }
      public virtual string UserName { get; set; }
      public virtual string FullName { get; set; }
      public virtual string Email { get; set; }
      public virtual string Password { get; set; }        
      public virtual IEnumerable&lt;string&gt; Roles { get; set; }
  
      public virtual IIdentity Identity { get; set; }
  
      public virtual bool IsInRole(string role)
      {
          if (Roles.Contains(role))
          {
              return true;
          }
          else
          {
              return false;
          }
      }
  
     //public string[] GetRolesForUser()
     //{
     //    return Roles;
     //}
  }
  </code></pre>
  
  <p>However when i run this I get the following error when the role provider tries to access the custom UserPrincipal object in the cookie</p>
  
  <p>"Unable to cast object of type 'System.Web.Security.RolePrincipal' to type 'MyApp.Domain.UserPrincipal'"</p>
  
  <p>Its like the custom role provider is overwriting the custom user principal im storing in the ticket with its own Role specific principal.</p>
  
  <p>Just wondering if what I'm trying to do is flawed or if theres an easier way. Dont want to reinvent the wheel.</p>
  
  <p>Anyone got an example of a custom role provider that does not hit the db on each request for roles?</p>