title: ASP.NET MVC2 Implementing Custom RoleManager problem
body: <p>To create a custom membership provider I followed these instructions:<br>
  <a href="https://stackoverflow.com/questions/2771094/asp-net-mvc2-custom-membership">How do I create a custom membership provider for ASP.NET MVC 2?</a> <br>
  and these:<br>
  <a href="http://mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx" rel="nofollow noreferrer">http://mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx</a></p>
  
  <p>So far, I've managed to implement custom membership provider and that part works fine. RoleManager still needs some modifications...</p>
  
  <p>Project structure:</p>
  
  <p><a href="http://img691.imageshack.us/img691/3875/21593096.gif" rel="nofollow noreferrer">alt text http://img691.imageshack.us/img691/3875/21593096.gif</a></p>
  
  <p>SAMembershipProvider.cs:</p>
  
  <pre><code>public class SAMembershipProvider : MembershipProvider
      {
  
          #region - Properties -
  
          private int NewPasswordLength { get; set; }
          private string ConnectionString { get; set; }
  
          public bool enablePasswordReset { get; set; }
          public bool enablePasswordRetrieval { get; set; }
          public bool requiresQuestionAndAnswer { get; set; }
          public bool requiresUniqueEmail { get; set; }
          public int maxInvalidPasswordAttempts { get; set; }
          public int passwordAttemptWindow { get; set; }
          public MembershipPasswordFormat passwordFormat { get; set; }
          public int minRequiredNonAlphanumericCharacters { get; set; }
          public int minRequiredPasswordLength { get; set; }
          public string passwordStrengthRegularExpression { get; set; }
  
          public override string ApplicationName { get; set; }
  
          public override bool EnablePasswordRetrieval
          {
              get { return enablePasswordRetrieval; }
          }
  
          public override bool EnablePasswordReset
          {
              get { return enablePasswordReset; }
          }
  
          public override bool RequiresQuestionAndAnswer
          {
              get { return requiresQuestionAndAnswer; }
          }
  
          public override int MaxInvalidPasswordAttempts
          {
              get { return maxInvalidPasswordAttempts; }
          }
  
          public override int PasswordAttemptWindow
          {
              get { return passwordAttemptWindow; }
          }
  
          public override bool RequiresUniqueEmail
          {
              get { return requiresUniqueEmail; }
          }
  
          public override MembershipPasswordFormat PasswordFormat
          {
              get { return passwordFormat; }
          }
  
          public override int MinRequiredPasswordLength
          {
              get { return minRequiredPasswordLength; }
          }
  
          public override int MinRequiredNonAlphanumericCharacters
          {
              get { return minRequiredNonAlphanumericCharacters; }
          }
  
          public override string PasswordStrengthRegularExpression
          {
              get { return passwordStrengthRegularExpression; }
          }
  
          #endregion
  
          #region - Methods -
  
          public override void Initialize(string name, NameValueCollection config)
          {
              throw new NotImplementedException();
          }
  
          public override bool ChangePassword(string username, string oldPassword, string newPassword)
          {
              throw new NotImplementedException();
          }
  
          public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
          {
              throw new NotImplementedException();
          }
  
          public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
          {
              throw new NotImplementedException();
          }
  
          public override bool DeleteUser(string username, bool deleteAllRelatedData)
          {
              throw new NotImplementedException();
          }
  
          public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
          {
              throw new NotImplementedException();
          }
  
          public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
          {
              throw new NotImplementedException();
          }
  
          public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
          {
              throw new NotImplementedException();
          }
  
          public override int GetNumberOfUsersOnline()
          {
              throw new NotImplementedException();
          }
  
          public override string GetPassword(string username, string answer)
          {
              throw new NotImplementedException();
          }
  
          public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
          {
              throw new NotImplementedException();
          }
  
          public override MembershipUser GetUser(string username, bool userIsOnline)
          {
              throw new NotImplementedException();
          }
  
          public override string GetUserNameByEmail(string email)
          {
              throw new NotImplementedException();
          }
  
          protected override void OnValidatingPassword(ValidatePasswordEventArgs e)
          {
              base.OnValidatingPassword(e);
          }
  
          public override string ResetPassword(string username, string answer)
          {
              throw new NotImplementedException();
          }
  
          public override bool UnlockUser(string userName)
          {
              throw new NotImplementedException();
          }
  
          public override void UpdateUser(MembershipUser user)
          {
              throw new NotImplementedException();
          }
  
          public override bool ValidateUser(string username, string password)
          {
              AccountRepository accountRepository = new AccountRepository();
              var user = accountRepository.GetUser(username);
  
              if (string.IsNullOrEmpty(password.Trim())) return false;
              if (user == null) return false;
  
              //string hash = EncryptPassword(password);
              var email = user.Email;
              var pass = user.Password;            
  
              if (user == null) return false;
  
              if (pass == password)
              {
                  //User = user;
                  return true;
              }
  
              return false;
          }
          #endregion
  
          protected string EncryptPassword(string password)
          {
              //we use codepage 1252 because that is what sql server uses
              byte[] pwdBytes = Encoding.GetEncoding(1252).GetBytes(password);
              byte[] hashBytes = System.Security.Cryptography.MD5.Create().ComputeHash(pwdBytes);
              return Encoding.GetEncoding(1252).GetString(hashBytes);
          }
  
      }
  </code></pre>
  
  <p>SARoleProvider.cs</p>
  
  <pre><code>public class SARoleProvider : RoleProvider
      {
          AccountRepository accountRepository = new AccountRepository();
  
          public override bool IsUserInRole(string username, string roleName)
          {
              return true;
          }
          public override string ApplicationName
          {
              get
              {
                  throw new NotImplementedException();
              }
              set
              {
                  throw new NotImplementedException();
              }
          }
          public override void AddUsersToRoles(string[] usernames, string[] roleNames)
          {
              throw new NotImplementedException();
          }
          public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
          {
              throw new NotImplementedException();
          }
          public override void CreateRole(string roleName)
          {
              throw new NotImplementedException();
          }
          public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
          {
              throw new NotImplementedException();
          }
          public override bool RoleExists(string roleName)
          {
              throw new NotImplementedException();
          }
          public override string[] GetRolesForUser(string username)
          {
              int rolesCount = 0;
              IQueryable&lt;RoleViewModel&gt; rolesNames;
  
              try
              {
                  // get roles for this user from DB...
                  rolesNames = accountRepository.GetRolesForUser(username);
                  rolesCount = rolesNames.Count();
  
              }
              catch (Exception ex)
              {
                  throw ex;
              }
  
              string[] roles = new string[rolesCount];
              int counter = 0;
              foreach (var item in rolesNames)
              {
                  roles[counter] = item.RoleName.ToString();
                  counter++;
              }
  
              return roles;
  
          }
          public override string[] GetUsersInRole(string roleName)
          {
              throw new NotImplementedException();
          }
  
          public override string[] FindUsersInRole(string roleName, string usernameToMatch)
          {
              throw new NotImplementedException();
  
          }
          public override string[] GetAllRoles()
          {
              throw new NotImplementedException();
  
          }
  
      }
  </code></pre>
  
  <p>AccountRepository.cs</p>
  
  <pre><code>public class RoleViewModel
      {
          public string RoleName { get; set; }
      }
  
      public class AccountRepository
      {
          private DB db = new DB();
  
          public User GetUser(string email)
          {
              return db.Users.SingleOrDefault(d =&gt; d.Email == email);
          }
          public IQueryable&lt;RoleViewModel&gt; GetRolesForUser(string email)
          {
  
              var result = (
                           from role in db.Roles
                           join user in db.Users on role.RoleID equals user.RoleID
                           where user.Email == email
                           select new RoleViewModel
                           {
                               RoleName = role.Name
                           });
  
              return result;
          }
      }
  </code></pre>
  
  <p>webconfig</p>
  
  <pre><code>&lt;membership defaultProvider="SAMembershipProvider" userIsOnlineTimeWindow="15"&gt;
        &lt;providers&gt;
          &lt;clear/&gt;
          &lt;add
            name="SAMembershipProvider"
            type="SA_Contacts.Membership.SAMembershipProvider, SA_Contacts"
            connectionStringName ="ShinyAntConnectionString"
            /&gt;
        &lt;/providers&gt;
      &lt;/membership&gt;
  
      &lt;roleManager defaultProvider="SARoleProvider" enabled="true" cacheRolesInCookie="true"&gt;
        &lt;providers&gt;
          &lt;clear/&gt;
          &lt;add
            name="SARoleProvider"
            type="SA_Contacts.Membership.SARoleProvider"
            connectionStringName ="ShinyAntConnectionString"
            /&gt;
        &lt;/providers&gt;
      &lt;/roleManager&gt;
  </code></pre>
  
  <p>AccountController.cs:</p>
  
  <pre><code>public class AccountController : Controller
      {
          SAMembershipProvider provider = new SAMembershipProvider();
          AccountRepository accountRepository = new AccountRepository();
  
          public AccountController()
          {
          }
  
          public ActionResult LogOn()
          {
              return View();
          }
  
          [AcceptVerbs(HttpVerbs.Post)]
          public ActionResult LogOn(string userName, string password, string returnUrl)
          {
  
              if (!ValidateLogOn(userName, password))
              {
                  return View();
              }
  
              var user = accountRepository.GetUser(userName);
              var userFullName = user.FirstName + " " + user.LastName;
  
              FormsAuthentication.SetAuthCookie(userFullName, false);
              if (!String.IsNullOrEmpty(returnUrl) &amp;&amp; returnUrl != "/")
              {
                  return Redirect(returnUrl);
              }
              else
              {
                  return RedirectToAction("Index", "Home");
              }
          }
  
          public ActionResult LogOff()
          {
  
              FormsAuthentication.SignOut();
              return RedirectToAction("Index", "Home");
          }
  
          private bool ValidateLogOn(string userName, string password)
          {
              if (String.IsNullOrEmpty(userName))
              {
                  ModelState.AddModelError("username", "You must specify a username.");
              }
              if (String.IsNullOrEmpty(password))
              {
                  ModelState.AddModelError("password", "You must specify a password.");
              }
              if (!provider.ValidateUser(userName, password))
              {
                  ModelState.AddModelError("_FORM", "The username or password provided is incorrect.");
              }
  
              return ModelState.IsValid;
          }
      }
  </code></pre>
  
  <p>In some testing controller I have following:</p>
  
  <pre><code>[Authorize]
      public class ContactsController : Controller
      {
  
          SAMembershipProvider saMembershipProvider = new SAMembershipProvider();
          SARoleProvider saRoleProvider = new SARoleProvider();
  
          //
          // GET: /Contact/
  
          public ActionResult Index()
          {
              string[] roleNames = Roles.GetRolesForUser("ilija@ilija.com");
  
              // Outputs admin
              ViewData["r1"] = roleNames[0].ToString();
  
              // Outputs True
              // I'm not even sure if this method is the same as the one below
              ViewData["r2"] = Roles.IsUserInRole("ilija@ilija.com", roleNames[0].ToString());
  
              // Outputs True
              ViewData["r3"] = saRoleProvider.IsUserInRole("ilija@ilija.com", "admin"); 
  
  
              return View();
          }
  </code></pre>
  
  <p>If I use attribute <code>[Authorize]</code> then everything works ok, but if I use <code>[Authorize(Roles="admin")]</code> then user is always rejected, like he is not in role.</p>
  
  <p>Any idea of what could be wrong here?</p>
  
  <p>Thanks in advance,<br>
  Ile</p>