我添加了一個帶有actionfilter的類,讓我知道當前記錄的用戶是否是Admin(記錄中的布爾值)。因爲我需要在許多視圖和控制器這個信息,我把動作過濾器在Global.asax中來自ActionFilter的ViewBag數據即使在數據庫後仍然保留在會話中
的問題是,如果用戶獲得更新和IsAdmin複選框被選中時,視圖不搶,除非新的更新信息我要麼重建項目,要麼重新開始視覺工作室。
這是我的代碼設置。
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>
}
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);
}
}
}
我可以看到編輯正在工作,因爲我可以驗證數據庫中的更改。
這裏是我用來更新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,但該部門的方法,如果我打開與其他瀏覽器,如火狐,數據應用仍然堅持。這是因爲它已被添加到global.asax?
以防萬一,我確認我剃刀的觀點是正確的,我添加
`<label>@ViewBag.AppUserIsAdmin</label>` to verify.
的問題是數據庫上下文沒有得到安置。我修改了我的動作過濾器。不過,我相信有一個更乾淨的方法來做到這一點。
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;
}
}
}
不確定這是否與您所看到的問題有關,但由於'CrewLogContext'是在類級別創建的,並且該類在'GlobalFilters.Filters'集合中被註冊爲單例,所以'CrewLogContext '實例從不處理。你應該把它放在一個使用塊中,或者使用DI將它注入到你的過濾器中。您可以使用[自定義FilterProvider](https://stackoverflow.com/a/38493666/)來允許一次性依賴項。 – NightOwl888
@ NightOwl888謝謝!我通過使用使用。我仍然會尋找一種更乾淨的方式來做到這一點,但現在這樣做。 – causita