ASP.NET会话状态/NInject/OnePerRequest行为出现问题

ASP.NET会话状态/NInject/OnePerRequest行为出现问题,asp.net,redirect,session-state,ninject,lifecycle,Asp.net,Redirect,Session State,Ninject,Lifecycle,这是一篇相当长的文章,请耐心听我说。我不确定这主要是关于ASP.NET会话状态行为、NInject、应用程序设计还是重构。继续读下去,然后你可以决定……:-) 背景 首先,一点背景知识。我们正在努力将一个大型网店重构为一个更易于维护的结构化设计。webshop目前运行在.NET3.5上,但其设计更多的是传统ASP时代的遗留问题。显然,我们不可能一下子解决所有问题,因此许多功能/技术/方法必须视为给定的。考虑到这一点 该应用程序在一个上下文对象中维护与当前会话(用户配置文件、购物车、会话选择等)有

这是一篇相当长的文章,请耐心听我说。我不确定这主要是关于ASP.NET会话状态行为、NInject、应用程序设计还是重构。继续读下去,然后你可以决定……:-)

背景 首先,一点背景知识。我们正在努力将一个大型网店重构为一个更易于维护的结构化设计。webshop目前运行在.NET3.5上,但其设计更多的是传统ASP时代的遗留问题。显然,我们不可能一下子解决所有问题,因此许多功能/技术/方法必须视为给定的。考虑到这一点

该应用程序在一个上下文对象中维护与当前会话(用户配置文件、购物车、会话选择等)有关的所有内容,该上下文对象只是一个大型XML文档,它作为字符串序列化到会话并从会话反序列化。XML格式也很重要,因为呈现是通过XSLT完成的

这导致了一些问题:

  • 这是一种神的物体,有远 太多的担忧
  • 它是松散类型的,并且过于依赖XML操作/XPath
  • 没有用于检索会话xml文档或将其写回的标准方法/模式。我们有一个可怕的混合方法,将文档作为一个参数,修改并返回它,方法自己检索它,修改它并将它保存回会话,等等。这导致了很多难以跟踪的错误,过度使用会话中的序列化/反序列化等
  • 我们的解决方案 我们所做的是尝试在xml文档周围引入一个强类型包装器,将其分解为不同的关注点,并对应用程序的其余部分透明地管理生命周期。
    我们的目标是实现以下工作流程:

    • 在请求开始时,我们填充 来自xml的会话文档 会话中存储的字符串

    • 应用程序的其余部分与之交互 只有通过强类型 包装纸。整个应用程序使用相同的 实例,不必担心 关于何时检索或保存 返回会话状态

    • 在请求结束时,底层xml文档被序列化回会话
    由于我们选择使用NInject(v1)作为IOC,因此我们决定使用它来管理上下文对象的生命周期。上下文对象用OnePerRequest属性包装,dispose方法连接到一个将xml文档作为字符串保存回会话的方法

    它不起作用。。。 我们很快遇到了一个问题,NInject OnePerRequest模块似乎无法访问SessionState。我们尝试的第一件事是,我们将会话对象保存在一个变量中,以确保我们仍然可以写入它。这似乎在开发机器上起作用,但当移动到进程外状态时,显然不起作用

    它仍然不起作用。。。 我们尝试从OnePerRequest行为/模块继承,并添加IRequiresessionState标记接口(OnePerRequestResessionState)。然而,这还不够,因为NInject用于释放引用和清理的方法与EndRequest方法相连接。会话在EndRequest中可用,但它已序列化到进程外状态服务器,因此在下一个请求开始时检索会话字符串时,不会反映现在更改的内容。 然后,我们决定改变偶数t以连接到。我们放弃了EndRequest,将OnePerRequestRequestResessionState“release all”方法连接到PostRequestHandlerExecute事件,该事件发生在会话数据从进程中序列化之前

    它是有效的。。。那它就不会。。。 这似乎奏效了。在单个服务器和web场上。然后我们注意到奇怪的行为。上下文似乎有两个不同的版本,您可以在它们之间随机切换。在购物车里加些东西,它不在那里。转到浏览到另一个产品,上一个产品将显示在购物车中

    经过一些追踪,我们发现了罪魁祸首:Response.Redirect。遍布整个网站的数百个地方就是Response.Redirect(url);。使用此版本的重定向,页面的执行会立即停止。这意味着PostRequestHandlerExecute不会被激发,并且当前版本的上下文对象不会被NInject丢弃。。。一切都崩溃了。新版本没有正确创建,等等。EndRequest被激发,这就是为什么正常的NInject OnePerRequest模块可以很好地使用它,而不是我们尝试使用会话状态的卑鄙版本

    当然,Response.Redirect有一个覆盖,您可以在其中传递一个布尔值,告诉它是终止现有页面还是继续执行-Response.Redirect(url,false)。很明显,继续进行会激发我们的活动,一切都正常,但是。。。它将继续执行页面的其余部分!这意味着执行重定向调用之后的所有操作,我们完全不知道这意味着什么(因为现有站点希望它停止)

    接下来呢? 那么,有什么建议吗?到目前为止,我们已经讨论过:

  • 抽象我们的行为 通过一个中心方法 控制重定向(可能是 找到一种方法来调用 PostRequestHandlerT或 可能是一个自定义重定向事件 我们的NInject模块也可以 订阅并清理)
  • 看看有没有办法 强制会话对象保存在中 EndRequest(如果尚未保存) 以前在 PostRequestHandlerExecute,并执行 ninject在EndRequest中进行清理
  • 删除对会话的依赖 完全关闭并使用另一个存储器 机制:数据库,文档数据库, 分布式哈希表等任何 建议?建议我们没有 虽然