Reputation: 3392
I have an MVC 5 data first app that I've been helping with. I made it use a filter to determine if the AD user is allowed certain functionality (via decorating methods/classes).
However, after changing a user's info in the db, the filter's context still has the old info for that user. The user 'edit' page keeps correct info though. Strange. This is happening just in the filter, not in any controller.
Here's the filter:
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (!base.AuthorizeCore(httpContext)) return false;
// Get the groups for this authorization (from the decoration attribute)
var groups = Groups.Split(',').ToList();
var userDisplayName = string.Empty;
using (HostingEnvironment.Impersonate())
{
// Verify that the user is in the given AD group (if any)
var context = new PrincipalContext(
ContextType.Domain);
var userPrincipal = UserPrincipal.FindByIdentity(
context,
IdentityType.SamAccountName,
httpContext.User.Identity.Name);
userDisplayName = userPrincipal.DisplayName;
}
// check for UserRoles for this
var user = _varDB.Users.FirstOrDefault(x => x.UserName == userDisplayName); //< Here is where it gets stale info...
IList<UserRole> usersRoles = new List<UserRole>();
if (user != null)
{
usersRoles = user.UserRoles.ToList();
}
// determine if the user is allowed to see this controller/page
foreach (var ur in usersRoles)
{
if (groups.Contains(ur.RoleName))
{
return true;
}
}
return false;
}
On the UserController, if I manually change the db, and refresh the page, I see the changes. But in this filter, if I change the data, it never changes until I recycle the app pool.
fyi, the top of the class goes like this:
public class AuthorizeByDbRoleAttribute : AuthorizeAttribute
{
private static ExtVariablesEntities _varDB = new ExtVariablesEntities();
}
If this filter doesn't get the updated user info, it can't keep users out of or let them use functionality if changed and the app pool isn't recycled.
Upvotes: 0
Views: 1624
Reputation: 3392
Problem was that a class that inherits from AuthorizeAttribute (or any attribute I believe) the class doesn't dispose of the context. I wound up wrapping the logic in a using like this:
using (ExtVariablesEntities _varDB = new ExtVariablesEntities())
{
// check for UserRoles for this
var user = _varDB.Users.FirstOrDefault(x => x.UserName == userDisplayName);
IList<UserRole> usersRoles = new List<UserRole>();
if (user != null)
{
usersRoles = user.UserRoles.ToList();
}
// determine if the user is allowed to see this controller/page
foreach (var ur in usersRoles)
{
if (groups.Contains(ur.RoleName))
{
return true;
}
}
}
This was the context get created each time this class method is hit.
Upvotes: 1