【问题标题】:What's causing “Session state has created a session id, but cannot save it because the response was already flushed by the application.”导致“会话状态已创建会话 ID,但无法保存它,因为响应已被应用程序刷新”的原因。
【发布时间】:2010-10-28 15:27:43
【问题描述】:

我间歇性地遇到此故障。

我发现这个链接很好地总结了我在 Google 上找到的内容: http://www.wacdesigns.com/2009/02/03/session-state-has-created-a-session-id-but-cannot-save-it-because-the-response-was-already-flushed-by-the-application/

基本上它说您可以尝试设置 Web 配置设置 DisplayWhenNewSession,或者尝试通过获取 Session_OnStart 中的 Session.SessionID 来激活会话状态。

但是有没有人:

a) 对此有解释

甚至更好,b) 有一个久经考验的修复方法

我意识到在执行任何会影响 http 响应标头的操作后,我无法刷新响应。如果我这样做,每次都会导致错误,但这是间歇性的。 SessionID 肯定应该由 ASP.NET 在页面响应开始时自动创建,在 ASPX 页面或 Page_Load(我的所有刷新都被调用的地方)中的任何内容之前。

更新: 经过反思,我意识到这是在将文件流式传输到浏览器时发生的。大多数浏览器实际上是搜索引擎机器人。我可以通过开始下载然后关闭浏览器来重新创建这个错误,所以大概浏览器在取消下载操作之前没有等待下载完成。我也在其他正常页面上看到过这种情况,但 99% 的时间是下载页面。

【问题讨论】:

标签: asp.net session-state


【解决方案1】:

我知道这已经很老了,但我发现了另一个可能适用于其他人的错误原因。如果您使用的是 MVC(我使用的是带有 .Net 4.0 的 MVC 4)并且您将页面设置为不缓冲 通过使用 web.config 元素

<pages buffer="false">    

然后,如果您在代码中尝试将数据推送到会话对象中,如果页面在您的子视图或操作执行会话状态访问之前开始呈现,则可能会出现此错误。

在这种情况下,您可以通过将上面的缓冲区设置更改为 true 来修复错误。或者,将您的会话访问代码移动到主视图而不是子操作/子视图中。

【讨论】:

    【解决方案2】:

    这个错误似乎出现在:

    • 应用程序启动

    • 您使用的是 Global.asax,即使您在 Session_Start / End 事件中是否正在做某事

    • 您的应用程序过早强制刷新响应

    • 你没有在刷新之前使用 Session

    当它试图在发布时保存 sessionID 时,它由会话状态引发:

    System.Web.SessionState.SessionIDManager.SaveSessionID(HttpContext context, String id, Boolean& redirected, Boolean& cookieAdded)
    System.Web.SessionState.SessionStateModule.CreateSessionId()
    System.Web.SessionState.SessionStateModule.DelayedGetSessionId()
    System.Web.SessionState.SessionStateModule.ReleaseStateGetSessionID()
    System.Web.SessionState.SessionStateModule.OnReleaseState(Object source, EventArgs eventArgs)
    System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
    

    我相信 Global.asax 的存在会导致会话 ID 在释放时由 SessionStateModule(迟到?)保存,即使在调用 SessionID 时没有使用会话代替 HttpSessionState。

    这就是string sessionId = Session.SessionID;技巧避免问题的原因。

    由于初始化行为,我猜它只出现在应用程序启动时。

    解决方案/技巧:

    • 如前所述,避免在 Page_Load 中刷新

    • 停用页面上的会话状态 (EnableSessionState)

    • 在刷新之前使用 SessionID 技巧

    • 如果您不关心刷新后可能发生的错误,请使用 Response.End() 代替 .Flush()

    【讨论】:

      【解决方案3】:

      我有!

      在 global.asax 文件中你这样做:

      void Session_Start(object sender, EventArgs e) 
      {
          // Code that runs when a new session is started
          string sessionId = Session.SessionID;
      }
      

      如此简单。有效!

      【讨论】:

      • 这是一种公共/受保护的方法 - 因为它是私有的,我想它应该受到保护。示例是否完整,没有保存 sessionId 的事实,我想这很好 - 重要的是触发创建,对吗?
      • 谢谢。我认为这通常有效,因此我会将其标记为已接受的答案,尽管我不是 100% 确定。如果他们发现这不起作用的情况,任何人都可以发表评论吗?谢谢。
      • 我只是将此方法添加到我的 global.asax 文件中,它消除了我的错误消息,这与问题相同,非常感谢 eitama!
      • 这解决了我的问题(我是在强制刷新)但是你知道为什么这是一个解决方案吗?
      • 这个答案为我节省了很多时间。永远不会猜到它。谢谢!
      【解决方案4】:

      我自己也遇到了这个问题,我想我会分享我的发现。

      web.config 设置 DisplayWhenNewSession 无关紧要,因为它仅适用于 Codeplex 上的一个特定自定义控件(抱歉,我丢失了链接)。

      另一个建议似乎可以通过尽早初始化 SessionId 来工作。我使用 Reflector 深入研究了代码,并不太明白这如何防止此处出现错误,但它确实对我们有用!

      像大多数似乎遇到此错误的人一样,我们没有在应用程序的任何地方显式调用 Response.Flush()。我们也在使用 MVC,作为记录。

      【讨论】:

        【解决方案5】:

        我认为这里的问题可能正是您在Page_Load 期间正在做一些事情导致页面输出,根据ASP.NET Page Lifecycle Overview,这在渲染阶段之前很久。

        确保在 PreRender 阶段之前,您永远不会做任何可能触发页面输出的事情。

        【讨论】:

        • 谢谢,今晚我会去看看。不知道为什么会断断续续?
        • 可能是不适当事件中的条件 Response.Write()?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-14
        • 1970-01-01
        • 2022-06-10
        • 2020-01-23
        • 1970-01-01
        相关资源
        最近更新 更多