我添加了一个带有actionfilter的类,让我知道当前登录的用户是否为Admin(记录中的bool)。因为我需要在许多视图和控制器中使用此信息,所以我将动作过滤器放在global.asax
中问题是,如果用户更新并且未选中IsAdmin Checkbox,则View不会获取新的更新信息,除非我重建项目或重新启动Visual Studio。
这是我的代码设置。
AppUser实体
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;
}
}
查看:如果用户是管理员,则切换显示链接。
@{
ViewBag.Title = "Index";
var isAdmin = ViewBag.AppUserIsAdmin;
}
<label>@ViewBag.AppUserIsAdmin</label>
@if (isAdmin)
{
<p>
@Html.ActionLink("Create New", "Create")
</p>
}
全球性的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);
}
}
}
我可以看到编辑工作正常,因为我可以验证数据库中的更改。
这是我用来更新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);
}
以防万一这是更新分配给此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);
}
}
}
}
我认为这是Chrome,但如果我用其他浏览器(如FireFox)打开应用程序,数据仍然存在。这是因为它已被添加到global.asax中吗?
为了防止我确认我的剃刀视图是正确的,我添加了
`<label>@ViewBag.AppUserIsAdmin</label>` to verify.
问题是db Context没有被处理掉。我修改了我的动作过滤器。但是,我确信有更简洁的方法可以做到这一点。
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;
}
}
}
答案 0 :(得分:0)
以防我将此作为答案。就像@ NightOwl888建议的那样,我必须处理上下文。 在动作过滤器中
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;
}
}
我会找到一种更清洁的方法,但至少它可以正常工作。