I added a class with an actionfilter to let me know if the current logged user is and Admin (bool on the record). Because I need this info in many views and controllers, I put the action filter in global.asax
The problem is that if the user gets updated and the IsAdmin Checkbox is unchecked, the View does not grab the new updated information unless I either rebuilt the project or visual studio gets restarted.
Here is my code setup.
AppUser Entity
public class AppUser
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "User Name")]
[Required]
public string Id { get; set; }
[Display(Name = "Display Name")]
[Required]
public string Name { get; set; }
public bool IsSuperUser { get; set; }
public bool IsAdmin { get; set; }
[Display(Name = "Default Location")]
public int LocationID { get; set; }
public virtual Location Location { get; set; }
public virtual ICollection<Department> Departments { get; set; }
}
ActionFilter:
public class AppUserActionFilter : System.Web.Mvc.ActionFilterAttribute
{
private CrewLogContext db = new CrewLogContext();
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//TODO remove repeating code..////////////
var currentAppUser = HttpContext.Current.User.Identity.Name.Split('\\')[1];
var appUser = db.AppUsers.Where(i => i.Id == currentAppUser).Single();
var currentAppUserLocation = appUser.LocationID;
var departments = appUser.Departments.ToList();
filterContext.Controller.ViewData.Add("AppUserDepartments", departments);
filterContext.Controller.ViewData.Add("AppUserLoca", currentAppUserLocation);
filterContext.Controller.ViewData.Add("appUser", appUser.Id);
//TODO remove repeating code..////////////
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
//Remove domain\ from windows authenticated user.
var currentAppUser = HttpContext.Current.User.Identity.Name.Split('\\')[1];
//Get user from db.
var appUser = db.AppUsers.Where(i => i.Id == currentAppUser).Single();
var currentAppUserLocation = appUser.LocationID;
//get IsAdmin flag.
//TODO not updating in VIEW
bool currentAppUserIsAdmin = appUser.IsAdmin;
//department related to user.
//TODO not updating in VIEW
var departments = appUser.Departments.ToList();
filterContext.Controller.ViewBag.AppUserDepartments = new SelectList(departments, "Id", "Name");
//Flag tells me if current user is ADMIN
filterContext.Controller.ViewBag.AppUserIsAdmin = currentAppUserIsAdmin;
filterContext.Controller.ViewBag.AppUserLocation = currentAppUserLocation;
}
}
View: Toggle display link if User is Admin or not.
@{
ViewBag.Title = "Index";
var isAdmin = ViewBag.AppUserIsAdmin;
}
<label>@ViewBag.AppUserIsAdmin</label>
@if (isAdmin)
{
<p>
@Html.ActionLink("Create New", "Create")
</p>
}
global asax.
namespace CrewLog
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalTrackingConfig.DisconnectedContext = true;
AreaRegistration.RegisterAllAreas();
//added actionfilter globally
GlobalFilters.Filters.Add(new AppUserActionFilter(), 0);
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
I can see the edit is working because I can verify the changes in the database.
Here the code that I'm using to update the AppUser.
[HttpPost]
[ValidateAntiForgeryToken]
//[Bind(Include = "Id,Name,IsSuperUser,IsAdmin,LocationID")]
public ActionResult Edit(string id,string[] selectedDepartments)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var appUserToUpdate = db.AppUsers
.Include(i => i.Location)
.Include(i => i.Departments)
.Where(i => i.Id == id).Single();
if(TryUpdateModel(appUserToUpdate,"",new string[] {"Name","IsAdmin","IsSuperUser","LocationID"}))
{
try
{
UpdateAppUserDepartments(selectedDepartments, appUserToUpdate);
db.SaveChanges();
return RedirectToAction("Index");
}
catch (RetryLimitExceededException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
}
PopulateAssignedDepartmentData(appUserToUpdate);
return View(appUserToUpdate);
}
and just in case here is the method that updates the departments assigned to this AppUser
private void UpdateAppUserDepartments(string[] selectedDepartments, AppUser appUserToUpdate)
{
if (selectedDepartments == null)
{
appUserToUpdate.Departments = new List<Department>();
return;
}
var selectedDepartmentsHS = new HashSet<string>(selectedDepartments);
var appUserDepartments = new HashSet<int>
(appUserToUpdate.Departments.Select(c => c.Id));
foreach (var department in db.Departments)
{
if (selectedDepartmentsHS.Contains(department.Id.ToString()))
{
if (!appUserDepartments.Contains(department.Id))
{
appUserToUpdate.Departments.Add(department);
}
}
else
{
if (appUserDepartments.Contains(department.Id))
{
appUserToUpdate.Departments.Remove(department);
}
}
}
}
I thought it was Chrome but if I open the app with other browser such as FireFox, the data still persisting. Is this because it has been added to the global.asax?
and just in case I'm verifying that my razor view is correct I added
`<label>@ViewBag.AppUserIsAdmin</label>` to verify.
The problem was the the db Context was not getting disposed. I modified my action filter. However, I'm sure there is a cleaner way to do this.
public class AppUserActionFilter : System.Web.Mvc.ActionFilterAttribute
{
//private CrewLogContext db = new CrewLogContext();
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//TODO remove repeating code..////////////
using (CrewLogContext db1 = new CrewLogContext())
{
var currentAppUser = HttpContext.Current.User.Identity.Name.Split('\\')[1];
var appUser = db1.AppUsers.Where(i => i.Id == currentAppUser).Single();
var currentAppUserLocation = appUser.LocationID;
var departments = appUser.Departments.ToList();
filterContext.Controller.ViewData.Add("AppUserDepartments", departments);
filterContext.Controller.ViewData.Add("AppUserLoca", currentAppUserLocation);
filterContext.Controller.ViewData.Add("appUser", appUser.Id);
}
//TODO remove repeating code..////////////
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
//Remove domain\ from windows authenticated user.
using (CrewLogContext db2 = new CrewLogContext())
{
var currentAppUser = HttpContext.Current.User.Identity.Name.Split('\\')[1];
//Get user from db.
var appUser = db2.AppUsers.Where(i => i.Id == currentAppUser).Single();
var currentAppUserLocation = appUser.LocationID;
//get IsAdmin flag.
//TODO not updating in VIEW
bool currentAppUserIsAdmin = appUser.IsAdmin;
//department related to user.
//TODO not updating in VIEW
var departments = appUser.Departments.ToList();
filterContext.Controller.ViewBag.AppUserDepartments = new SelectList(departments, "Id", "Name");
//Flag tells me if current user is ADMIN
filterContext.Controller.ViewBag.AppUserIsAdmin = currentAppUserIsAdmin;
filterContext.Controller.ViewBag.AppUserLocation = currentAppUserLocation;
}
}
}