How can I change the ASP.Net MVC Login Redirect based on role?

12,277

Solution 1

The reason your code is not working as expected is because the User has technically not been signed in and authenticated yet. Say what? But you did call SignIn!

FormsAuth.SignIn(userName, rememberMe); - which in this case is just a wrapper for FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); - only sets the asp.net authorization cookie on the users browser as part of the response. It is only for requests after this point that the user's browser will have the cookie, causing the asp.net membership to properly set up the 'User' object. All of your code in the LogOn method is still assuming an anonymous user, so your IsInRole check fails and you are redirected home. Put your if statement on another page and after you've signed in, you'll see that now User.IsInRole works as expected. (And indeed, this is what you'd use User.IsInRole for, just not during the logon process)

So how to check during the actual logon process? Roles.IsUserInRole or Roles.GetRolesForUser are a couple of ways, eg.:

if (Roles.IsUserInRole(userName, "Administrator") || Roles.IsUserInRole(userName, "Administrator"))
{
    return RedirectToAction("Index", "AdminApp");
}

You must explicitly specify the user name of the user logging in, which will actually execute a query against the membership datastore. On that note, I believe the above code would as a result cause two queries to be executed, which you may find less than ideal. This is where Roles.GetRolesForUser might be a better option:

string[] roles = Roles.GetRolesForUser(userName);
if (roles.Contains("Administrator") || roles.Contains("Manager"))
{
    return RedirectToAction("Index", "AdminApp");
}

Hope that helps!

Solution 2

I'm using VS 2013 and it's new Identity model, I ended up going with this:

foreach (IdentityUserRole identityUserRole in user.Roles)
{
   if (identityUserRole.RoleId == "AdminRoleId")
   {
     return RedirectToAction("Index", "Admin");
   }
   else if (identityUserRole.RoleId == "MemberRoleId")
   {
     return RedirectToAction("Index", "Members");
   }
 }
Share:
12,277
Ben
Author by

Ben

I'm very new to programming and I'm learning ASP.net MVC. I expect at first I'll be asking more than responding, but I hope to get up to speed soon and start helping others.

Updated on June 04, 2022

Comments

  • Ben
    Ben about 2 years

    I have the following code I've typed into the Account Controller in my MVC project and I am in both the administrator and manager roles. When I log in I get redirected back to my home index instead of being redirected to my AdminApp index. Any ideas where I'm going wrong in my code?

    [AcceptVerbs(HttpVerbs.Post)]
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
            Justification = "Needs to take same parameter type as Controller.Redirect()")]
        public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
        {
    
            if (!ValidateLogOn(userName, password))
            {
                    return View();
            }
    
            FormsAuth.SignIn(userName, rememberMe);
            if (!String.IsNullOrEmpty(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                if (User.IsInRole("Administrator") || (User.IsInRole("Manager")))
                {
                    return RedirectToAction("Index", "AdminApp");
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
    
            }
        } 
    
  • Ben
    Ben over 14 years
    hmm. I tried and didn't work for me. I can use the User.InInRole successfully on an aspx page to show/hide links, but it's not working when I have it in a controller. Is there another way to perform this in the controller?
  • Jeff French
    Jeff French over 14 years
    Shouldn't make much difference, but you can try Roles.IsUserInRole(). However, I think this is the same method that ends up getting called by the User.IsInRole() method.