Obiekt reprezentujący pojedynczą stronę internetową istnieje tylko w momencie
zwrócenia odpowiedzi na zapytanie klienta, po czym jest natychmiast niszczony.
Zapamiętywanie wartości liczbowych, znakowych, czy całych obiektów, jako jego
właściwości jest więc niemożliwe (tzn. jest możliwe, ale na dłuższą metę nie
przynosi żadnych, interesujących nas korzyści). Zastanawiacie się zapewnie, w
jaki sposób można przechowywać obiekty, między kolejnymi zapytaniami do serwera.
W rozdziale tym postaram się przedstawić kilka najbardziej popularnych technik.
W celu zrozumienia zasad działania poszczególnych metod przechowywania stanu w
aplikacjach internetowych, będziemy musieli przyjrzeć się bliżej cyklowi życia
tejże aplikacji. Aplikacja "żyje" tak długo, dopóki istnieją aktywne sesje w
obrębie tej aplikacji. Dla wielu w Was, brzmi to zapewnie dość enigmatycznie.
Wszystko rozpoczyna się w momencie, kiedy w oknie przeglądarki po raz pierwszy
zostaje wyświetlona strona, wchodząca w skład naszej aplikacji. Jak zapewnie
pamiętacie, aby to nastąpiło, na serwerze musi zostać uruchomiona nowa
aplikacja, która z kolei wygeneruje obiekt, opisujący zawartość strony (WebForm),
która zwracana jest do klienta. Po wykonaniu tej czynności obiekt ten jest
natychmiast niszczony. Działanie aplikacji się jednak nie kończy. Użytkownik
posiada, bowiem cały czas aktywną sesję z aplikacją. A oprogramowania
znajdującego się na serwerze może korzystać jednocześnie wiele osób. Każda z
nich jest posiadaczem aktywnej sesji. Okres działania aplikacji kończy się w
momencie, kiedy nie istnieją dla niej żadne sesje użytkowników. Sesja kończy się
w określonym, ustalonym czasie (standartowo jest to dwadzieścia minut) braku
aktywności użytkownika. Środowisko uruchomieniowe stwierdza wówczas, że obiekty
aplikacji nie są już używane, dochodzi, więc do ich zniszczenia (zajmuje się tym
"odśmiecacz" – ang. garbage collector).
Przejdźmy teraz do właściwego tematu tego rozdziału. Dwie pierwsze metody
zapamiętywania stanu aplikacji internetowej, które chciałbym zaprezentować, to
przechowywanie zmiennych w obiektach sesji i aplikacji. Odbywa się to
następująco:
Session["NazwaZmiennej"] = zmienna;
Application["NazwaZmiennej"] = zmienna;
Tak wygląda natomiast odczytywanie obiektów.
zmienna = (klasa_obiektu)Session["NazwaZmiennej"]
zmienna = (klasa_obiektu) Application ["NazwaZmiennej"]
W ten sposób mogą być zapisywane i odczytywane zarówno typy proste, jak i całe
obiekty. W przeważającej większości przypadków odczytywania zmiennych, należy
wcześniej dokonać rzutowania. Poniższy przykład pokaże różnice, a także
zademonstruje możliwość wykorzystania opisanego sposobu zapamiętywania
aplikacji.
Prace należy rozpocząć od stworzenia nowej aplikacji ASP.NET (File ->New -> Web
Site -> ASP.NET Web Site). Następnie dodajmy do aplikacji nowy plik. Klikamy
prawym przyciskiem myszy na wyświetloną w Solution Explorerze, lokalizację
naszej aplikacji i wybieramy opcję: "Add New Item". Następnie, w nowo-otwartym
oknie obiekt "Global Application Class". Pozostawiamy jego domyślną nazwę - "Global.asax".
Zajrzyjmy teraz do wnętrza nowego dokumentu. Przedstawia się ono następująco:
<%@
Application
Language="C#"
%>
<script
runat="server">
void Application_Start(Object
sender, EventArgs e) {
// Code that runs on application
startup
}
void
Application_End(Object sender,
EventArgs e) {
// Code that runs on application
shutdown
}
void
Application_Error(Object sender,
EventArgs e) {
// Code that runs when an unhandled
error occurs
}
void
Session_Start(Object sender,
EventArgs e) {
// Code that runs when a new session
is started
}
void
Session_End(Object sender,
EventArgs e) {
// Code that runs when a session ends.
// Note: The Session_End event is
raised only when the sessionstate mode
// is set to InProc in the Web.config
file. If session mode is set to StateServer
// or SQLServer, the event is not
raised.
}
</script>
Widzimy, że plik ten zawiera metody obsługi zdarzeń, związanych z cyklem życia
aplikacji ASP.NET. Dwie pierwsze metody: "Application_Start" i "Application_End"
– uruchamiane są w momentach, odpowiednio rozpoczęcia i zakończenia działania
aplikacji. Metoda "Application_Error" jest często wykorzystywana do obsługiwania
błędów, pojawiających się w czasie działania programu. Natomiast "Session_Start"
i "Session_End" związane są z procesami rozpoczęcia i zakończenia sesji, dla
poszczególnych użytkowników aplikacji. Wyobraźmy sobie teraz, że pragniemy
umieścić na stronie internetowej informację, ile osób korzysta jednocześnie z
naszej aplikacji. Pierwszym krokiem do tego będzie modyfikacja (a raczej
uzupełnienie) metody "Application_Start".
void Application_Start(Object sender, EventArgs e) {
Application["LiczbaUzytkownikow "] = 0;
Application["LiczbaUzytkownikow"] = (int)Application["LiczbaUzytkownikow"]
+ 1;
}
W momencie rozpoczęcia działania aplikacji, zerujemy zmienną, zawierającą liczbę
użytkowników serwisu, a następnie zwiększamy ją o jeden. Wynika to z tego, że
aby aplikacja rozpoczęła działanie przynajmniej jeden użytkownik musi spróbować
się do niej odwołać. Wprowadzamy również zmiany w kolejnych metodach, zawartych
w pliku Global.asax.
void Session_Start(Object sender, EventArgs e) {
Application["LiczbaUzytkownikow"] = (int)Application["LiczbaUzytkownikow"]
+ 1;
}
void Session_End(Object sender, EventArgs e) {
Application["LiczbaUzytkownikow"] = (int)Application["LiczbaUzytkownikow"]
- 1;
}
W momencie wejścia na naszą stronę kolejnego użytkownika i co się z tym wiąże
rozpoczęcia działania kolejnej sesji, liczba użytkowników, zapamiętywana z
obiekcie aplikacji jest zwiększana o jeden. Odwrotnie – w przypadku wygaśnięcia
sesji (co najczęściej związane jest, z zakończeniem wykorzystywania programu
przez użytkownika) – następuje dekrementacja tej zmiennej.
Proponuje spróbować wyświetlić zawartość naszej zmiennej na ekranie. W tym celu
na formatce, wchodzącej w skład aplikacji, umieszczamy kontrolkę typu "Label", a
następnie uzupełniamy metodę Page_Load naszej formatki w następujący sposób:
protected void Page_Load(object sender, EventArgs e)
{
this.Label1.Text = "Ilość gości na stronie: " +
Application["LiczbaUzytkownikow"];
}
Efekt działania kodu, przy pierwszym uruchomieniu strony, powinien wyglądać
następująco:

Zmienne, zapamiętywane w obiekcie aplikacji są wspólne dla wszystkich jej
użytkowników w danym momencie. Natomiast te, zapisywane w sesji są (podobnie jak
sama sesja) unikalne dla każdego użytkownika. Możemy sobie wyobrazić
hipotetyczną sytuację, kiedy na początku użytkowania strony użytkownik podaje
swoje imię i nazwisko. Dane te, wyświetlane są na kolejnych podstronach i są
unikalne dla każdego użytkownika aplikacji.
Session["Imie"] = this.txtFirst_Name.Text;
Session[“Nazwisko"] = this.txtLast_Name.Text;
Label1.Text = “Nazywasz się: “ + Session["Imie"] + "" + Session[“Nazwisko"]
Gdzie, txtFirst_Name i txtLast_Name są kontrolkami typu: "TextBox".
Na zakończenie zajmijmy się przypadkiem, w którym chcemy wyłączyć dostęp do
sesji dla określonych stron, wchodzących w skład naszej aplikacji. Dokonać tego
możemy na dwa sposoby. W pierwszym przypadku, we właściwościach strony (na
przykład, wykorzystując okno: "Properties") ustalamy wartość właściwości
EnableSessionState = false. Możemy również wyłączyć obsługę sesji dla całej
aplikacji. W tym przypadku dodajemy do projektu plik Web.config (robimy to w
taki sam sposób, jak w przypadku Global.asax, tyle że tym razem w stosownym
oknie wybieramy: "Web Configuration File"), a następnie, między znacznikami <system.web></system.web>
dodajemy linijkę:
<sessionState mode="Off" />