我有以下全局过滤器代码:
public class UserAuthorizationFilter : FilterAttribute, IAuthorizationFilter
{
private readonly IAdministratorService _administratorService;
public UserAuthorizationFilter()
{
_administratorService = IoCFactory.Container.GetInstance<IAdministratorService>();
}
public void OnAuthorization(AuthorizationContext filterContext)
{
string username = HttpContext.Current.User.Identity.Name;
IRequestMessage<string> request = MessageFactory.BuildRequestFor(username, username);
Administrator administrator = _administratorService.GetDetailByName(request).Data;
filterContext.Controller.ViewBag.Username = username;
filterContext.Controller.ViewBag.IsAdmin = administrator != null;
if (administrator != null)
{
bool isManageRole = administrator.Roles.Any(r => r.IsManageRole);
bool isManageAdministrator = administrator.Roles.Any(r => r.IsManageAdministrator);
bool isManageReviewer = administrator.Roles.Any(r => r.IsManageReviewer);
filterContext.Controller.ViewBag.IsManageRole = isManageRole;
filterContext.Controller.ViewBag.IsManageAdministrator = isManageAdministrator;
filterContext.Controller.ViewBag.IsManageReviewer = isManageReviewer;
}
}
}
我在 global.asax 的 Application_Start 事件中添加了这个过滤器:
GlobalFilters.Filters.Add(new UserAuthorizationFilter(), 0);
当我将管理员角色属性(例如 IsManageRole)从 true
更新为 false
时,数据已成功更新到数据库。然而在管理员对象的 UserAuthorizationFilter
属性角色没有更新,它仍然加载 true
值。我试过调用 sessionFactory.Evict(typeof(Role))
、session.Clear()
但没有成功。数据仍然不会加载新的更新 Role 属性。如果我重新启动 Web 应用程序,属性会更新。
我该如何解决这个问题?为什么 nhibernate 缓存不会用上面的函数清除和更新,有什么建议吗?请帮助..
最佳答案
在这里看到 IAdministratorService
的实现会很有趣, 它如何缓存 .GetDetailByName(request)
的结果 方法调用。
要点是:ASP.NET MVC 过滤器是/可以被视为单例。请参阅:Are ActionFilterAttributes reused across threads? How does that work? :
...In ASP.NET MVC 3, filters are cached more aggressively. Therefore, any custom action filters which improperly store instance state might be broken...
让我们想想它们,它们被实例化一次,它们永远存在而无需“重建”。 IE。没有通过构造函数的新 IoC/DI。
可能有更多方法可以解决这个问题。
I. 肮脏的方法是调用 IoCFactory.Container.GetInstance<IAdministratorService>();
在每个OnAuthorization()
.这很可能会返回全新的服务,并可以访问当前 session 中的新数据。它应该可以工作......但是:Service Locator is an Anti-Pattern通过马克·西曼
II. 请参阅 Brad Wilson 撰写的有关提供 filters in MVC 的文章主要是部分:向过滤器添加依赖注入(inject)。简而言之,每个属性都使用 Unity IoC 通过 setter 注入(inject)来丰富。查看过滤器提供程序的片段:
var attributes = base.GetActionAttributes(controllerContext,
actionDescriptor);
foreach (var attribute in attributes) {
_container.BuildUp(attribute.GetType(), attribute);
}
III. 我会选择一些以提供者模式为代表的共享“应用程序缓存”。 (尽管 Mark Seemann 的 Provider is not a pattern)。
- 过滤器将与一些
SecurityManager
通信. - 会有一些单例
SecurityProvider
,从当前 session 中获取新数据并缓存它们。 - 缓存将在一段合理的时间后被清理(为了安全我会说几分钟)
- “安全”对象上的事件系统也将触发
cache.Clear()
- AOP Mvc 过滤器将有权访问最新的安全数据
关于c# - 如何从全局过滤器的 NHibernate session 中获取更新的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27090052/