c# - 如何从全局过滤器的 NHibernate session 中获取更新的对象

标签 c# asp.net-mvc nhibernate asp.net-mvc-5

我有以下全局过滤器代码:

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/

相关文章:

asp.net - 构建 nhibernate 的标准

database - NHibernate 可以持久保存到平面文件而不是数据库吗?

c# - Microsoft.SqlServer.Management.Smo 获取 SQL Server 的恢复模型

c# - 从包含通用 O​​bservableCollection 的类型 (System.type) 中获取字符串 "System.Collections.ObjectModel.ObservableCollection"?

c# - 将 ASP MVC 应用程序部署到普通共享托管服务提供商时遇到问题

vb.net - 删除 NHibernate 表中的所有行

c# - 如何改进 Entity Framework 和 Javascript 交互

c# - Angular http获取使用c#.Net

asp.net-mvc - SignalR——来自多个局部 View 的连接?

sql-server - asp.net mvc - 扩展注册页面(成员(member)资格)与新用户表(个人资料) - 它们是同一件事吗?