2

我有一个 ASP.Net Web API 项目。我在这个项目中使用 NHibernate;Fluent NHibernate 是具体的。我正在使用自定义 ActionFilterAttribute 处理 NHib 会话管理。它看起来像这样:

public class SessionManagement : ActionFilterAttribute
{
    public SessionManagement()
    {
        SessionFactory = WebApiApplication.SessionFactory;
    }

    private ISessionFactory SessionFactory { get; set; }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var session = SessionFactory.OpenSession();
        CurrentSessionContext.Bind(session);
        session.BeginTransaction();
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        var session = SessionFactory.GetCurrentSession();
        var transaction = session.Transaction;
        if (transaction != null && transaction.IsActive)
        {
            transaction.Commit();
        }
        session = CurrentSessionContext.Unbind(SessionFactory);
        session.Close();
    }

这很适合我的需求。但是,我最近添加了一个自定义 JSON.NET MediaTypeFormatter 来格式化我的操作生成的 JSON。我遇到的问题是我的 ActionFilter OnActionExecuted() 方法在 MediaTypeFormatter 的 WriteToStreamAsync 可以完成工作之前被调用。结果是延迟加载的(问题)集合现在不可用,因为会话已关闭。处理这个问题的最佳方法是什么?我应该删除 ActionFilter 的 OnActionExecuted 方法并在 MediaTypeFormatter 中关闭我的会话吗?

谢谢!!

4

1 回答 1

1

MediaTypeFormatter 是关闭会话的错误层,因为此行为实际上与您正在使用的特定格式化程序无关。这是我建议做的事情:

  1. 从 HttpContent 派生并创建从 ObjectContent 派生的类。覆盖 SerializeToStreamAsync 实现以等待基本实现的 SerializeToStreamAsync 然后关闭会话:

    public class SessionClosingObjectContent : ObjectContent
    {
        private Session _session;
    
        public SessionClosingObjectContent(Type type, object value, MediaTypeFormatter formatter, Session session)
            : base(type, value, formatter)
        {
            _session = session;
        }
    
        protected async override Task SerializeToStreamAsync(Stream stream, TransportContext context)
        {
            await base.SerializeToStreamAsync(stream, context);
            // Close the session and anything else you need to do
            _session.Close();
        }
    }
    
  2. 现在在您的操作过滤器中,您希望将响应内容替换为关闭会话的新类,而不是关闭会话:

    public class SessionManagement : ActionFilterAttribute
    {
        public SessionManagement()
        {
            SessionFactory = WebApiApplication.SessionFactory;
        }
    
        private ISessionFactory SessionFactory { get; set; }
    
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var session = SessionFactory.OpenSession();
            CurrentSessionContext.Bind(session);
            session.BeginTransaction();
        }
    
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            var session = SessionFactory.GetCurrentSession();
            var response = actionExecutedContext.Response;
            if (response.Content != null)
            {
                ObjectContent objectContent = response.Content as ObjectContent;
                if (objectContent != null)
                {
                    response.Content = new SessionClosingObjectContent(objectContent.ObjectType, objectContent.Value, objectContent.Formatter, session);
                    foreach (KeyValuePair<string, IEnumerable<string>> header in objectContent.Headers)
                    {
                        response.Content.Headers.TryAddWithoutValidation(header.Key, header.Value);
                    }
                }
            }
        }
    }
    

您也可以选择直接从您的控制器代码返回一个带有新内容的 HttpResponseMessage,无论您需要什么。

于 2013-06-10T00:43:53.867 回答