Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Horas
Člen
Avatar
Horas:19.8.2019 8:38

Používám Session pro udržení o přihlášení a obsahu košíku ve web aplikaci. Na lokálním spuštění mi to vše funguje, ale jak aplikaci nahraju na webhosting, Session fungují jen chvíli a poté svévolně ztrácí informaci.

Zkusil jsem: Při různém testování na webhositngu mí přišlo, že vše ovlivňuje množství datového přenosu. Tedy, že čím více dat přenáším, tím dříve Session ztratí niformaci. Ale to je jen moje domněnka.

Chci docílit: Nevím jak udržet informaci v Session na potřebnou dobu (na webhostingu). Zkrátka, aby vše fungovalo jako na lokále. Může mi to někdo vysvětlit? Díky předem

 
Odpovědět
19.8.2019 8:38
Avatar
Odpovídá na Horas
Neaktivní uživatel:19.8.2019 9:06

Životnost session lze ovlivnit přes nastavení php, konkrétně session.gc_max­lifetime a session.cooki­e_lifetime.

Zkus si zkontrolovat, jestli tam nejsou nějaké nestandardní hodnoty, default je 1440 a 0.

Nahoru Odpovědět
19.8.2019 9:06
Neaktivní uživatelský účet
Avatar
Horas
Člen
Avatar
Odpovídá na Neaktivní uživatel
Horas:19.8.2019 9:24

Mám to napsané v C# a jak jsem psal, na lokále ta samá aplikace funguje.

Editováno 19.8.2019 9:25
 
Nahoru Odpovědět
19.8.2019 9:24
Avatar
Ghst
Člen
Avatar
Odpovídá na Horas
Ghst:19.8.2019 9:51

Jak píše Dan, zkontroluj nastavení ISS položku časový limit relace. Na lokále pracuješ s jiným serverem, který může mít jiné nastavení než ten webhostingový.

 
Nahoru Odpovědět
19.8.2019 9:51
Avatar
zelvicek
Člen
Avatar
Odpovídá na Horas
zelvicek:19.8.2019 10:20

Je třeba si uvědomit, jak se Session data ukládají. Obecně: pro uložení dat je potřeba místo (RAM/disk/DB/...). Pokud ukládáš mnoho dat, potřebuješ mnoho místa.
Nepíšeš, jak Sessions ukládáš (In-process memory nebo nějaké perma úložiště). Předpokládám, že in-process memory.
Může docházet k tomu, že pokud požaduješ příliš RAM, IIS recykluje pooly - tzn. shodí starou aplikaci/process a nahodí novou.
Taky nepíšeš, zda se session "ztratí" vždy po stejné době nebo nahodile (z pohledu času).
Další věcí je LoadBalancing - pokud aplikaci provozuješ na více serverech, musíš sessions sdílet. Je asi jasné, že si servery navzájem do pamětí nevidí.

OT: pro veřejný web bych se sessions vyhnul. Vhodná náhrada může být JWT.

 
Nahoru Odpovědět
19.8.2019 10:20
Avatar
Odpovídá na Horas
don.jarducius:19.8.2019 10:42

Jak píše @zelvicek, server jednou za stanovený čas nebo po určitém eventu recykluje aplikační pool.
In-process memory na webhostingu vůbec nepoužívej. Ideální je pro tebe uložiště na SQLServer, nebo StateSterver. Informace v session pak přežijí restart aplikace i serveru a dají se sdílet i v rámci více serverů.

Nastavuje se ve Web.config:

<system.web>
    <sessionState mode=" SQLServer" allowCustomSqlDatabase="true" sqlConnectionString="tvůj connection string" />
</system.web>

Má to ale malý háček, informace, které do session ukládáš se musejí dát serializovat nebo musejí být označeny atributem Serializable.

Tady máš odkaz na návod jak to nastavit pro ukládání do SQL DB

Nahoru Odpovědět
19.8.2019 10:42
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
Odpovídá na Horas
Neaktivní uživatel:19.8.2019 11:21

Uhh promiň, vůbec mi nedocvaklo podívat se na kategorii :-X automaticky jsem bral PHPčko

Nahoru Odpovědět
19.8.2019 11:21
Neaktivní uživatelský účet
Avatar
Horas
Člen
Avatar
Odpovídá na don.jarducius
Horas:19.8.2019 15:50

SQLServer uložiště se mi povedlo rozběhnout na lokále, super, ale nevím jak nakonfigurovat SQL server na webhostingu. Systémovou databázi tempdb tam sice mají, ale neobsahuje tabulky ASPStateTempAp­plications, ASPStateTempSes­sions. Zkrátka nevím jak tam dostat ty potřebné věci. Mužeš mi poradit.

 
Nahoru Odpovědět
19.8.2019 15:50
Avatar
Odpovídá na Horas
don.jarducius:20.8.2019 10:29

Ty 2 tabulky nemusí být v tempDB, můžeš je mít i ve své DB, . Důležitá je i údržba tabulky ASPStateTempSes­sions, dokáže docela rychle nabobtnat. Stačí v ní mazat exspirované řádky - sessiony (where [Expires] < getdate())

Nahoru Odpovědět
20.8.2019 10:29
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
Horas
Člen
Avatar
Horas:21.8.2019 9:52

Tak už jsem to rozběhl, co se týče ukládání Session na SQL všude. Při změně InProc na SQLServer mi ale přestávají fungovat AJAX. Volám jim ActionResult v Controlleru a až po

...
Session["cart"] = cart;
return Json(cart, JsonRequestBehavior.AllowGet);

to jede stejně. Verze InProc to vrátí zpět do AJAX a dá se s tím dál pracovat, ale verze SQLServer se do AJAX už nevrátí.
Zkoušel jsem serializovat třídy, s kterými to souvisí, ale nic se nezměnilo.

 
Nahoru Odpovědět
21.8.2019 9:52
Avatar
Odpovídá na Horas
don.jarducius:21.8.2019 10:42

Session s tím souviset nebude, co ti přiletí zpět do prohlížeče v odpovědi na ten ajax?
Nejsou jinak pojmenovaný pole, velikost písmen, vím že si json serializer v MVC dokáže dělat s názvy co chce :)

Nahoru Odpovědět
21.8.2019 10:42
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
Horas
Člen
Avatar
Horas:21.8.2019 12:06

Tak chybu mám v ActionResult v tom zápisu do Session. Jakmile vyřadím Session["cart"]=car­t, pak AJAX funguje normálně. Asi úplně dobře nevím jak a co serializovat. Co všechno musím označit atributem Serializable?

 
Nahoru Odpovědět
21.8.2019 12:06
Avatar
Horas
Člen
Avatar
Odpovídá na don.jarducius
Horas:21.8.2019 15:00

Problém je v tom, že do Session ukládám něco takového:

List<EshopItem> cart = new List<EshopItem>();

cart.Add(new EshopItem { Product = productModel.find(id), Quantity = quantity });
Session["cart"] = cart;

Všechny třídy, kterých se to dotklo jsem označil [Serializable()], ale ničemu to nepomohlo.

 
Nahoru Odpovědět
21.8.2019 15:00
Avatar
Odpovídá na Horas
don.jarducius:21.8.2019 15:07

Vyhazuje to výjimku, nebo pak zdánlivě v sessioně nic není?

Nahoru Odpovědět
21.8.2019 15:07
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
Horas
Člen
Avatar
Odpovídá na don.jarducius
Horas:21.8.2019 15:10

V Session je vše uloženo, na SQL se to taky tváří, že něco zapsal, ale jak jsem psal dříve, nevrátí mi příkaz:

return Json(cart, JsonRequestBehavior.AllowGet);

hodnoty zpátky do pohledu.

 
Nahoru Odpovědět
21.8.2019 15:10
Avatar
Odpovídá na Horas
don.jarducius:21.8.2019 15:17

Ok, v konzoli prohlížeče v sekci síť sedí odpověď serveru s očekáváním? Nevidím totiž žádný důvod proč by to nemělo vrátit data...

Nahoru Odpovědět
21.8.2019 15:17
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
Horas
Člen
Avatar
Odpovídá na don.jarducius
Horas:22.8.2019 12:41

Právě v té odpovědi mám chybu. Pokud v controlleru nepoužívám ukládání do Session mám:

Status Code: 200 OK
Response Headers
Content-Type: applications/json; cahrset=utf--8

Jakmile odblokuju ukládání do Session:

Status Code: 500 Internal Server Error
Response Headers
Content-Type: text/html; cahrset=utf--8

Nevím jak se vypořádat s tím Content -Type, což je jediný rozdíl.

 
Nahoru Odpovědět
22.8.2019 12:41
Avatar
Horas
Člen
Avatar
Horas:22.8.2019 13:50

Ještě mi to píše:
Stav relace nelze serializovat. V režimu StateServer a SQLServer bude technologie ASP.NET serializovat objekty stavu relace, a v důsledku toho nejsou objekty bez možnosti serializace nebo objekty MarshalByRef povoleny. Stejné omezení platí v případě, že je podobná serializace provedena vlastním úložištěm stavu relace v režimu Custom.

[Serializatio­nException: Typ System.Data.En­tity.DbContext v sestavení EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c56­1934e089 není označen jako serializovatelný.]

 
Nahoru Odpovědět
22.8.2019 13:50
Avatar
don.jarducius:22.8.2019 14:35

Jasně… To znamená že nemáš všechny své vlastní třidy, které se ukládají do Sessiony, označené atributem [Serializable]

Projdi všechny třídy které se mohou dostat do session zda mají atribut [Serializable], resp. všechny své třídy/modely opatři atributem [Serializable].

List<EshopItem> cart = new List<EshopItem>();

cart.Add(new EshopItem { Product = productModel.find(id), Quantity = quantity });
Session["cart"] = cart;
Nahoru Odpovědět
22.8.2019 14:35
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
Horas
Člen
Avatar
Odpovídá na don.jarducius
Horas:22.8.2019 17:08

Označil jsem třídy/modely [Serializable], ale chyba přetrvávala.

Tak jsem zkusil testovat od základů co projde. Nakonec jsem dospěl k vytvoření třídy stejné jako EshopItem(stejné vlastnosti, bez metod) a s ní to prošlo. Takže problém je někde v těch metodách.

 
Nahoru Odpovědět
22.8.2019 17:08
Avatar
Odpovídá na Horas
don.jarducius:22.8.2019 20:18

A všechny vlastní třídy, které jsou jako property ve třídě EshopItem jsou taky označeny Serializable?

Nahoru Odpovědět
22.8.2019 20:18
Ten kdo nechce hledá důvod, ten kdo chce hledá způsob
Avatar
zelvicek
Člen
Avatar
Odpovídá na Horas
zelvicek:22.8.2019 21:04

Konečně jsme se někam pohli - a stačilo uvést konkrétní chybu.
Předpokládám, že

productModel.find(id)

načítá data z DB pomocí EF.
Zkus si vypsat

productModel.find(id).GetType().AssemblyQualifiedName

. Myslím, že budeš překvapen.

 
Nahoru Odpovědět
22.8.2019 21:04
Avatar
Horas
Člen
Avatar
Odpovídá na don.jarducius
Horas:23.8.2019 8:57

Problém vyřešen, všechny vlastní třídy byly označeny Serializable, ale celé to blokoval řádek v rámci třídy EshopItem pro DBContext, což nebylo nutné tam mít.

private EshopDBEntities db = new EshopDBEntities();

Třída EshopDBEntities je public partial a měl jsem ji také označenou Serializable, ale přesto to nefungovalo. Nevím jestli by šlo její serializování vyřešit nějak jinak, ale já ji inicializuji v controlleru a do metody ve třídě EshopItem ji předávám jako parametr. Každopádně díky za pomoc.

Akceptované řešení
+5 Zkušeností
Řešení problému
 
Nahoru Odpovědět
23.8.2019 8:57
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 23 zpráv z 23.