我遇到了一个奇怪的问题。我已经设置了MVC 4应用程序和NHibernate,然后是ASP.NET MVC4 and the Web API published by apress
中的说明。
我使用名为[LoggingNhibernateSessionAttribute]
的控制器属性管理操作的会话。它运行良好,我可以使用NHibernate进行CRUD操作。
但是当我向HomeController添加authorize
属性并重定向到登录页面时,会出现问题。目前发生异常表明
“没有会话绑定到当前上下文”
我看了很多代码。但我无法理解为什么会话不会绑定当前的上下文。
public class LoggingNHibernateSessionAttribute : ActionFilterAttribute
{
private readonly IActionLogHelper _actionLogHelper;
private readonly IActionExceptionHandler _actionExceptionHandler;
private readonly IActionTransactionHelper _actionTransactionHelper;
public LoggingNHibernateSessionAttribute()
: this(WebContainerManager.Get<IActionLogHelper>(),
WebContainerManager.Get<IActionExceptionHandler>(),
WebContainerManager.Get<IActionTransactionHelper>())
{
}
public LoggingNHibernateSessionAttribute(
IActionLogHelper actionLogHelper,
IActionExceptionHandler actionExceptionHandler,
IActionTransactionHelper actionTransactionHelper)
{
_actionLogHelper = actionLogHelper;
_actionExceptionHandler = actionExceptionHandler;
_actionTransactionHelper = actionTransactionHelper;
}
public override void OnActionExecuting(ActionExecutingContext actionExectingContext)
{
_actionLogHelper.LogEntry(actionExectingContext.ActionDescriptor);
_actionTransactionHelper.BeginTransaction();
}
public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
{
_actionTransactionHelper.EndTransaction(actionExecutedContext);
_actionTransactionHelper.CloseSession();
_actionExceptionHandler.HandleException(actionExecutedContext);
_actionLogHelper.LogExit(actionExecutedContext.ActionDescriptor);
}
}
ActionTransactionHelper
public ActionTransactionHelper(
ISessionFactory sessionFactory,
ICurrentSessionContextAdapter currentSessionContextAdapter)
{
_sessionFactory = sessionFactory;
_currentSessionContextAdapter = currentSessionContextAdapter;
}
public void BeginTransaction()
{
var session = _sessionFactory.GetCurrentSession();
if (session != null)
{
session.BeginTransaction();
}
}
以及如何将会话绑定到当前sessionContext:
private ISession CreateSession(IContext context)
{
var sessionFactory = context.Kernel.Get<ISessionFactory>();
if (!CurrentSessionContext.HasBind(sessionFactory))
{
// Open new ISession and bind it to the current session context
var session = sessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
}
return sessionFactory.GetCurrentSession();
}
有没有人有任何想法?
答案 0 :(得分:1)
此处的问题与IFilter
属性的执行顺序有关,如下所述:Understanding Action Filters (下面引用)
ASP.NET MVC框架支持四种不同类型的过滤器:
- 授权过滤器 - 实现IAuthorizationFilter属性。
- 操作过滤器 - 实现IActionFilter属性。
- 结果过滤器 - 实现IResultFilter属性。
- 异常过滤器 - 实现IExceptionFilter属性。
醇>过滤器按上面列出的顺序执行。例如,在操作过滤器和异常过滤器总是在每种其他类型的过滤器之后执行之前,始终执行授权过滤器。
所以,我们所经历的是:
一种解决方案是在OnAuthorize
事件中启动会话......
答案 1 :(得分:0)
我是如何解决的:
public class AuthorizaAttributeWithSession : AuthorizeAttribute
{
private readonly ISessionFactory _sessionFactory;
public AuthorizaAttributeWithSession () : this(WebContainerManager.Get<ISessionFactory>())
{
}
public AuthorizaAttributeWithSession(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
var session = _sessionFactory.GetCurrentSession();
if (session != null)
{
session.BeginTransaction();
}
base.OnAuthorization(filterContext);
}
}
和我的AdiminstratorAuthorize过滤器:
public class AdministratorAuthorized : AuthorizaAttributeWithSession
{
public AdministratorAuthorized()
{
Roles = "Administrators";
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
}
}