Click here to Skip to main content
15,912,329 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am developing a MVC 5 application with custom role provider, but it seems that the Authorize Attribute never call my customer role provider, my code is as below:

C#
namespace SIMSPortal.Models
{
public class MyCustomRoleProvider:RoleProvider
{
public override string[] GetRolesForUser(string username)
    {
        //throw new NotImplementedException();
        using(var usersContext = new SchoolPortalEntities())
        {
            var user = usersContext.login_details.SingleOrDefault(u =>       u.user_id == username);
if(user == null)
                return new string[] { };
            return user.UserInRoles == null ? new string[] { } :
              user.UserInRoles.Select(u => u.Role).Select(u => u.RoleName).ToArray();

        }          
    }



}
}    

public override bool IsUserInRole(string username, string roleName)
        {
            //throw new NotImplementedException();
            using(var usersContext = new SchoolPortalEntities())
            {
                var user = usersContext.login_details.SingleOrDefault(u => u.user_id == username);
                if(user == null)
                    return false;
                return user.UserInRoles != null && user.UserInRoles.Select(
                     u => u.Role).Any(r => r.RoleName == roleName);
            }
        }


my config file:

C#
<roleManager defaultProvider="CustomRoleProvider" enabled="true" cacheRolesInCookie="false">
      <providers>
        <clear />
        <add name="CustomRoleProvider" type="SIMSPortal.Models.MyCustomRoleProvider" />
      </providers>
    </roleManager>


However, my custom role provider is in Model folder, and i am using EF DB first approach, I am able to call my custom role provider method with following code within my controller:
C#
String[] roles = Roles.GetRolesForUser(userId);


However any controller where [Authorize] attribute is being used, users are always redirect to the login page, even when user login and role are both valid. This same code works fine using MVC4. Please help
Posted
Updated 11-Oct-15 23:53pm
v2
Comments
John C Rayan 12-Oct-15 7:53am    
Are you checking the roles in the same action of login? Can you show code for [Authorize] and roles check.
Uwakpeter 12-Oct-15 9:16am    
Login Action:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UserLogin([Bind(Include = "user_id, password")] login_details loginDetails, string returnUrl)
{
var objUser = _db.login_details.FirstOrDefault(
x => x.user_id == loginDetails.user_id && x.password == loginDetails.password);
if (objUser == null)
{
ModelState.AddModelError("LogOnError", "The user name or password provided is incorrect.");
}
else
{
FormsAuthentication.SetAuthCookie(loginDetails.user_id, false);

if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
//Redirect to default page
TempData["userId"] = loginDetails.user_id;
return RedirectToAction("RedirectToDefault", "Login");
}
}

return View(loginDetails);

}


public ActionResult RedirectToDefault()
{
string userId = TempData["userId"].ToString();
Session["userId"] = userId;
String[] roles = Roles.GetRolesForUser(userId);
if(roles.Contains("ClassTeacher"))
{
return RedirectToAction("ValidateReceipt", "ClassTeacher", new { id = userId });
}
if(roles.Contains("Student"))
{
return RedirectToAction("Home", "DashBoardStudents", new { id = userId });
}
if(roles.Contains("Teacher"))
{
return RedirectToAction("Index", "PublicUser", new { id = userId });
}
if(roles.Contains("Admin"))
{
return RedirectToAction("ValidateReceipt", "ClassTeacher", new { id = userId });
}
if(roles.Contains("Parent"))
{
return RedirectToAction("Index", "PublicUser", new { id = userId });
}
else
{
FormsAuthentication.SignOut();
Session["userId"] = null;
return RedirectToAction("Index","Home");
}
}

Authorized Controller:
[Authorize(Roles = "Student")]
public class DashBoardStudentsController : Controller
{
SchoolPortalEntities db = new SchoolPortalEntities();
// GET: DashBoardStudents
public ActionResult Home()
{
string userId = Session["userId"].ToString();
var userDetail = db.students_biodata.FirstOrDefault(s => s.user_id == userId);
if (userDetail != null)
{
ViewBag.ImgPath = userDetail.pic_id;
ViewBag.UserId = Session["userId"].ToString();
ViewBag.DisplayName = "Welcome " + userDetail.first_name;
}
return View();
}
}
John C Rayan 13-Oct-15 7:27am    
Can you debug and confirm that the roles.contains() works in RedirectToDefault()
method and it definitely is going into the DashBoardStudentsController
Uwakpeter 13-Oct-15 8:40am    
yes, i have done that sir, the roles.Contains() actually picks the right role, and it will attempt to redirect to DashboardStudentsController, upon hitting the Authorize(Roles="Student") it will be redirected to the login page. I actually created my own userLogin Action and Logincontroller for this, but whenever i use the default Login action in the AccountController, it will not be redirected to the RedirectToDefault action, i dont really know whether the issue is from me creation my own Login action and Controller, i did this because the default wasn't hitting the GetRolesForUser(string username) in the custom role provider i created at all. Please i will appreciate if you could still assist. Thanks
John C Rayan 13-Oct-15 9:15am    
Can you check inside RedirectToDefault() method , all the properties of GenericPrincipal. Authorize will call IsInRole() on User. Are you using Identity? If so , use UserManager and get the user and check. As far as I can see you are not loading roles to the user anywhere in your authentication. Another solution would be you have to write a Custom Authorize attribute.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900