即使在数据库

时间:2017-10-19 20:50:57

标签: c# asp.net-mvc razor asp.net-mvc-5

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



    }

1 个答案:

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

我会找到一种更清洁的方法,但至少它可以正常工作。