Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tento blog post ponímam jednak ako informáciu pre čitateľov, jednak ako možnú diskusiu k problému.

Takže k veci :

Mal som pocit, že uschovanie si nejakej menšej premennej do objektu Session a následný Response.Redirect na nejakú url kde ju vyberiem zo Session a použijem je bežný a OK spôsob ako fungovať, ak nechcem hodnotu premennej vystaviť na obdiv a pokusy na hack pre usera cez query string. Teda myslel som si to až doposiaľ. V jednej našej aplikácii však potrebujeme (resp. celkom sa hodí) preniesť cez session väčší objekt. (Aký je to väčší objekt? Rádovo MB, v každom prípade nie 4 znaky stringu). No a tu nastáva problém o ktorom som netušil. Pri použití Response.Redirect nastáva totiž ThreadAbortException. Prečo? Nuž, vraj preto, lebo sa ukončuje thread ktorým sme si vyžiadali stránku a pokračujeme na novú. Túto informáciu dostanete aj vo VS v okne Output asi v takomto tvare :

A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll

Čo sa teda stalo? Nastala exception ThreadAbortException aj v kóde, až na to, že redirect nastane a teda o nej ani nevieme. Vieme ju normálne chytiť v try/catch, no veľa sa nedozvieme, len toľko, že nastala mimo náš kód. Zaujímavé použiť ako druhý parameter vo volaní Redirect hodnotu false. Nuž, nedopracujete sa síce k výnimke a váš request nepadne, no interne výnimka nastane opäť a opäť prídeme o Session. Celú. Bohužiaľ. Aj tu sú však výnimky. Aplikáciu máme nasadenú na 2 rôznych mašinách, obe majú W2k3, IIS6 a na jednej aplikácia dáta v session prenesie, na inej nie. Rozdiel by som musel vyskúmať, každopádne na všetkých dev mašinách nám tento kód padá a session maže a preto sa nechcem spoliehať na to, že na 1 z x mašín kód ide, na ostatných nie.

Všimol som si ale, že pár bajtová premená prežije. Ak si však uložíme niečo väčšie, session stratíme.

Čo teda môžeme robiť?

Po pravde neviem. Trochu som sa poohliadol po webe a došiel som na pár zaujímavých linkov :

http://support.microsoft.com/kb/312629 - údajne to tak má byť a všetko je OK. spomína sa použite false ako druhého parametru, no mne nepomáha,

http://weblogs.asp.net/bleroy/archive/2004/08/03/Don_2700_t-redirect-after-setting-a-Session-variable-_2800_or-do-it-right_2900_.aspx - rovnako aj tu je spomenuté riešenie, ktoré mne nefunguje,

http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=15 - spomenuté Server.Transfer, ktoré som vyskúšal a opäť sa v Output dostavila výnimka.

Posledný pokus bol Server.Execute - popis nájdete na http://msdn.microsoft.com/en-us/library/ac8t9s7b.aspx. Pri tomto síce výnimku nedostaneme, no ani request nepresmerujeme, takže som vyčerpal všetko čo som dnes našiel na webe ale bez výsledku.

Chcem sa teda spýtať, čo robím zle? Prípadne ako to robiť tak, aby to fungovalo Smile

Vopred ď a prajem Vám všetkým všetko dobré do roku 2010 Big Smile

 

Update 1:

Upravím pár informácií, ktoré som uviedol nepresne. Nepredávame si celý niekoľko MB objekt, ale len názov súboru na disku. Na začiatku PageLoad držíme v Session 3 objekty, tieto sú 2 stringy a 1 menšia štruktúra (niekoľko stringov, nič veľké). Pred Redirect-om si pridáme 4 ďalšie objekty (medzi nimi aj názov súboru a 1 ďalšiu štruktúru a teda máme v Session 7 objektov). Potom vykonáme redirect, po ňom na presmerovanej page je Session stále s rovnakým ID, no len s 3 objektami, ktoré boli v Session predtým, ako sme vstúpili na PageLoad stránky kde sa redirectovalo. Je to vcelku logické, zahodili sme všetky zmeny, ktoré sme vykonali na stránke, kde sme redirectovali. No v mojom malom sample, ktorý som si urobil som dokázal uchovať v Session objekt, ktorý som vložil a následne na ďalšom riadku redirectoval. Zvláštne.

 

Update 2:

V catch za Response.Redirect Session stále obsahuje 7 objektov, až v PageBase presmerovanej stránky už máme len 3. Velice zajímavé Smile

Publikované Monday, January 04, 2010 2:00 PM dudok

Komentáre

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 05, 2010 10:39 AM duracellko

Ak nepomáha Redirect False, tak potom si napísať vlastný redirect. Z hlavy neviem ako sa presne robí, ale stačí nastaviť Response.StatusCode na neviem aké číslo a ešte asi do nejakej hlavičky nastaviť, kam sa to má presmerovať.

aj keď redirect false by mal robiť presne toto isté.

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 05, 2010 12:02 PM dudok

no však len to je tá zábava, ten blázon to neurobí sám dobre... :/ ach jaj

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 05, 2010 12:16 PM skippo

rostacik: nakolko sa ti bajty prenesu, mozno haluzi serializacia. Vyskusaj si ten objekt manualne serializovat na pole bytov a to si poslat cez session.

Resp opacit ako by sa to chovalo so session serverom, resp session v databaze. Pretoze ako sa v nejakom clanku co si poslal spravne pise, pokial to mas vo webfarme za nejakym loadbalancerom tak ti request moze skoncit na uplne inom fyzickom hoste ako bol ten pred redirektom spracovany.

Skuste len tak pokusne povolit uchovavanie session na jednom sql serveri a uvidite.

Keby uz nic nepomahalo, tak v ASP.NET MVC mas v controlleri okrem property ViewData aj novu property TempData, ktora sluzi presne na to co chces. Prenesie data medzi requestom a nasledujucim requestom. Skus stiahnut zdrojaky a pozriet ako to implementovali.

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 05, 2010 12:49 PM dudok

no len 3 veci :

- neje to na farme, je to len jedno IIS6,

- ja som tiež rozmýšľal použiť sql server na držanie session, ale čo keď tam zákazník nebude mať ms sql?? ho neprinútim si ho dať kvôli tomuto a toto je presne tento prípad :(,

- je to webforms, takže vymoženosti MVC bye,bye :(((

snažím sa prísť na to, ako to celé funguje, kedy prídem o časť session a kedy nie... asi sa na to mrknem cez reflector...

pozriem sa na tú serializáciu...

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 05, 2010 1:35 PM skippo

dudok:

- ten sql state server len kvoli oddebugovaniu a lokalizovaniu problemu. podla mna to bude nejaka blbost a nakoniec ti to normalne pofrci in-proc.

- mvc a TempData -> to som ti poslal ako inspiraciu, ako oni implementovali ten redirect. viem, ze robis webforms ale mozes sa inspirovat a porovnat ako ste to implementovali vy a ako hosi z ms. fakt ako posledne riesenie, ale ako  som pisal, myslim, ze to bude len nejaka blbost v konfiguracii.

- application pools si skontroloval?

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 05, 2010 2:11 PM Peter Širka

Dudok nemáš v Session uložený class ktorý niekde disposneš?

Nerobíš niečo takéto?:

using (var d = new Object())

 Session["d"] = d;

// dúfam že nie som od témy, lebo som to nečítal celé len námatkovo.

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 05, 2010 2:14 PM dudok

no pohrám sa s tým sql serverom. je to vážna haluška...

pooly? no čo presne by som mal kuknúť?? :)

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 05, 2010 2:29 PM dudok

no nemyslím že tam niečo podobné robíme, nieje to ale môj kód, nevidel som ho úplne celý :)

v každom prípade, ak spravím Server.Transfer Session prežije, len sa page vyrenderovala zle. ak použijem redirect (len zamením riadok, nič iné nezmením), tak sa stratí. záhada :)

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 05, 2010 8:18 PM vlko

Podľa mna je problém inde. A to v potrebe preniesť x MB dat medzi dvoma requestami. Už len ich samotné držanie v pamäti je do oči bijuce;) Predstav si, že ti zákazník otvorí par takýchto okien, stačí pár krát refresh a máš dos útok ako vysity. Odporúčal by som preto použitie nejakého storage riešenia napríklad sql lite, pripadne staticka premenna per application.

Session je okrem toho bez záruky, že bude existovať medzi dvoma requestami podobne ako je to s cache. Pri session mame aspoň istotu, že sa pri jej inicializacii v global.asax zavola session start.

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Thursday, January 07, 2010 10:22 AM vlko

Tak ma este napadlo, ci vlozenie takeho mnozstva dat nevyvola recycling poolu. Testol by som preto, ci druhy request po redirecte nevytvara novu session.

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Thursday, January 07, 2010 1:18 PM dudok

session id je rovnaká a preto som si myslel, že k tomu nedôjde, ale ako som sa dočítal, session id sa vzťahuje ku mne, ku mojím requestom, odosielam ju v cookies a hoci sa session recykluje, vraj mám stále rovnaké id. no vyriešili sme to naledovne, skúsili sme StateServer. museli sme ale odekorovať triedy atribútom Serializable, po krátkych testoch session prežije po Response.Redirect tak, ako by som očakával. Na použitie StateServera treba zapnúť proces ASP.NET State Service vo win. Poinformujem vás o výsledku :)

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Monday, January 11, 2010 2:33 PM dudok

tak zatiaľ to funguje so StateServerom. strata serializáciou by mala byť 15%. zaujímavé je, že StateServer nepotrebuje nainštalovaný SQL server a teoreticky môže byť na inej mašine... no uvidíme :)

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 12, 2010 10:08 AM ig

Stateserver a sql server mod su dve rozdielne veci. Stateserver je z pohladu ukladania dat to iste ako InProc, teda data uklada do operacnej pamate. Dovod jeho vzniku a urcenie pouzitia su webove farmy, kde vsetky servre v clustri potrebuju vidiet tie iste session data.

# re: Ako správne Redirectovať, aneb kam sa schovala moja premenná v session?

Tuesday, January 12, 2010 1:12 PM dudok

áno, sú, len som myslel, na prvý pohľad, že bude treba urobiť viac, ako len zapnúť nejaký servis niekde ...