Co powoduje „Stan sesji utworzył identyfikator sesji, ale nie można go zapisać, ponieważ odpowiedź została już opróżniona przez aplikację”.

80

Od czasu do czasu otrzymuję ten błąd.

Znalazłem ten link, który dość dobrze podsumowuje to, co udało mi się znaleźć w Google: http://www.wacdesigns.com/2009/02/03/session-state-has-created-a-session-id-but- nie można-zapisać-ponieważ-odpowiedź-została-już-opróżniona-przez-aplikację /

Zasadniczo mówi, że możesz spróbować ustawić ustawienia konfiguracji sieci Web DisplayWhenNewSession lub spróbować uruchomić stan sesji, pobierając Session.SessionID w Session_OnStart.

Ale czy ktoś:

a) mieć na to wyjaśnienie

lub nawet lepiej, b) mieć wypróbowaną i przetestowaną poprawkę

Zdaję sobie sprawę, że nie mogę opróżnić odpowiedzi po zrobieniu czegokolwiek, co wpłynęłoby na nagłówek odpowiedzi http. Gdybym to zrobił, spowodowałoby to błąd za każdym razem, ale jest to przerywane. SessionID z pewnością powinien zostać automatycznie utworzony przez ASP.NET na początku odpowiedzi strony, przed czymkolwiek na stronie ASPX lub Page_Load (gdzie są wywoływane wszystkie moje opróżnienia).

Aktualizacja: Po namyśle zdaję sobie sprawę, że dzieje się tak podczas przesyłania strumieniowego pliku do przeglądarki. Większość przeglądarek to w rzeczywistości boty wyszukiwarek. Mogę odtworzyć ten błąd, rozpoczynając pobieranie, a następnie zamykając przeglądarkę, więc prawdopodobnie przeglądarki nie czekają na zakończenie pobierania przed anulowaniem operacji pobierania. Widziałem to również na innych, zwykłych stronach, ale w 99% przypadków są to strony pobierania.

mike nelson
źródło
1
Mam dokładnie ten sam problem. Jedynym powodem, dla którego to w ogóle widziałem, było umieszczenie obsługi wyjątków w Global.asax. To jest bardzo sporadyczne. Byłoby wspaniale, gdyby ktoś znał odpowiedź na to pytanie!
Scott Ferguson,
6
Link jest teraz uszkodzony :-(
Casebash

Odpowiedzi:

85

Mam!

W pliku global.asax robisz to:

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

Tak łatwo. To działa!

eitama
źródło
Czy to metoda publiczna / chroniona - ponieważ jest prywatna, myślę, że powinna być chroniona. Czy próbka jest kompletna, fakt, że sessionId nie jest zapisany, jak sądzę, jest w porządku - ważne jest, aby wyzwolić kreację, prawda?
Chris Kimpton
Dzięki. Myślę, że to generalnie działa, więc oznaczę to jako zaakceptowaną odpowiedź, chociaż nie jestem w 100% pewien. Czy ktoś może skomentować, jeśli znajdzie przypadek, w którym to nie działa? Dzięki.
mike nelson,
Po prostu dodałem tę metodę do mojego pliku global.asax i pozbyłem się mojego komunikatu o błędzie, który był taki sam jak pytanie, wielkie dzięki eitama!
vanhornRF
To rozwiązało mój problem (wymuszałem rzut) Ale czy wiesz, dlaczego to działa jako rozwiązanie?
Polubowny
Ta odpowiedź właśnie zaoszczędziła mi wielu godzin. Nigdy bym tego nie domyślił. Dziękuję Ci!
HockeyJ
23

Ten błąd pojawia się, gdy:

  • Uruchomienie aplikacji

  • Używasz Global.asax, nawet jeśli robisz coś w zdarzeniach Session_Start / End, czy nie

  • Twoja aplikacja wymusza Flush odpowiedzi zbyt wcześnie

  • Nie używasz sesji przed spłukiwaniem

Jest podnoszony przez stan sesji podczas próby zapisania sessionID w momencie wydania:

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)

Uważam, że obecność Global.asax powoduje, że identyfikator sesji jest zapisywany po zwolnieniu przez SessionStateModule (późno?), Nawet jeśli nie użyto żadnej sesji zamiast HttpSessionState, gdy wywoływana jest SessionID.

To jest powód, dla którego string sessionId = Session.SessionID;sztuczka uniknąć problemu.

Wydaje mi się, że pojawia się tylko przy starcie aplikacji z powodu zachowań inicjalizacyjnych.

Rozwiązania / sztuczki :

  • Unikaj płukania w Page_Load, jak już powiedziano

  • Dezaktywuj stan sesji na stronie (EnableSessionState)

  • Użyj sztuczki SessionID przed flush

  • Użyj Response.End () zamiast .Flush (), jeśli nie dbasz o błędy, które mogą wystąpić po flush

JoeBilly
źródło
6

Uważam, że problem może polegać na tym, że robisz coś, co powoduje wyświetlenie strony, podczas Page_Loadktórej, zgodnie z omówieniem cyklu życia strony ASP.NET jest na długo przed etapem renderowania.

Upewnij się, że nie robisz niczego, co mogłoby spowodować wyświetlenie strony, aż do zakończenia PreRenderetapu.

cjs
źródło
Dzięki, przyjrzę się temu wieczorem. Nie wiesz, dlaczego miałoby to być przerywane?
mike nelson
może warunkowa Response.Write () w nieodpowiednim zdarzeniu?
Josh E.
3

Po tym, jak sam napotkałem ten problem, pomyślałem, że podzielę się swoimi odkryciami.

Ustawienie DisplayWhenNewSession w web.config jest nieistotne, ponieważ dotyczy tylko jednej konkretnej kontrolki niestandardowej w Codeplex (przepraszam, że zgubiłem łącze).

Druga sugestia wydaje się działać dzięki wczesnej inicjalizacji SessionId. Zagłębiłem się w kod za pomocą Reflectora i nie mogłem do końca zobaczyć, jak to zapobiegło występowaniu błędu, ale z pewnością zadziałało!

Podobnie jak większość ludzi, u których wydaje się, że napotyka ten błąd, nie wywołujemy wprost metody Response.Flush () w dowolnym miejscu aplikacji. Dla przypomnienia używamy również MVC.

Gaz
źródło
0

Zdaję sobie sprawę, że jest to bardzo stare, ale znalazłem inny powód błędu, który może dotyczyć innych. Jeśli używasz MVC (używałem MVC 4 z .Net 4.0) i ustawiłeś strony tak, aby nie były buforowane przy użyciu elementu web.config

<pages buffer="false">    

Jeśli w swoim kodzie spróbujesz wypchnąć dane do obiektu sesji, możesz ryzykować wystąpienie tego błędu, jeśli strona zaczęła renderować się przed widokiem podrzędnym lub działaniem wykonującym dostęp do stanu sesji.

W takich przypadkach możesz naprawić błąd, zmieniając powyższe ustawienie bufora na true. Ewentualnie przenieś kod dostępu do sesji do widoku głównego, a nie do akcji podrzędnej / widoku podrzędnego.

Mike Teye
źródło