2017-10-19 70 views
-1

我添加了一个带有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; 
      } 
     } 



    } 
+0

不确定这是否与您所看到的问题有关,但由于'CrewLogContext'是在类级别创建的,并且该类在'GlobalFilters.Filters'集合中被注册为单例,所以'CrewLogContext '实例从不处理。你应该把它放在一个使用块中,或者使用DI将它注入到你的过滤器中。您可以使用[自定义FilterProvider](https://stackoverflow.com/a/38493666/)来允许一次性依赖项。 – NightOwl888

+0

@ NightOwl888谢谢!我通过使用使用。我仍然会寻找一种更干净的方式来做到这一点,但现在这样做。 – causita

回答

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; 
     } 
    } 

我会找到一个更清洁的方式做,但至少它的工作,因为它应该。

相关问题