BETA
Aby się zalogować, najpiew wybierz portal.
Aby się zarejestrować, najpiew wybierz portal.
Podaj słowa kluczowe
Słowa kluczowe muszą mieć co najmniej 3 sąsiadujące znaki alfanumeryczne
Pole zawiera niedozwolone znaki

Baza wiedzy











Przekazywanie danych między stronami w ASP .NET 2.0

30-09-2007 12:09 | zooly
Jak przekazać wybrane informacje do następnej strony? Parametry URL, sesja czy ciasteczka? A może są lepsze sposoby? Wielu programistów ASP .NET codziennie stawia sobie te pytania. Uzyskanie odpowiedzi wymaga zazwyczaj długiej lektury dokumentacji, blogów, ale nie każdy ma na to czas. Artykuł zawiera omówienie dostępnych w ASP .NET 2.0 metod przekazywania danych między stronami wraz z porównaniem i praktycznymi poradami dotyczącymi ich stosowania.

Wstęp

W artykule przedstawiono omówienie następujących metod przekazywania danych między stronami:

·         parametry URL

·         ciasteczka

·         przekierowania po stronie serwera

·         Cross-Page Posting

·         sesja

 

Opisy metod uzupełnione zostały wieloma przykładami kodu, dostępne jest także ich podsumowanie w formie tabeli.

Parametry URL

Parametry URL są, obok ciasteczek (ang. cookies), stosowane na wszystkich platformach do tworzenia dynamicznych stron internetowych. Wiele kontrolek ASP .NET (np. GridView, FormView, DetailsView) zawiera mechanizmy ułatwiające tworzenie sparametryzowanych odnośników.

Jak dołączyć do odnośnika parametry URL? Do adresu strony (np. http://www.mysite.pl)  należy dodać znak ‘?’ oraz pary klucz=wartość oddzielone od siebie znakiem &.

 

Przykład:

http://www.mysite.pl?parametr1=wartosc1

http://www.mysite.pl?parametr1=wartosc1¶metr2=wartosc2

 

 

Wartość parametrów URL możemy uzyskać z poziomu każdej strony i kontrolki ASP .NET za pośrednictwem kolekcji dostępnej przez Request.QueryString.

 

Zalety:

·         respektowane przez wszystkie przeglądarki, nie da się ich „wyłączyć”

·         przyjazne dla użytkowników (możliwość dodawania strony do „ulubionych”)

·         widoczność z poziomu skryptów JavaScript

 

Wady:

·         jawność przekazywanych informacji

·         możliwość ingerencji ze strony użytkownika

·         praktyczne ograniczenie długości adresów w przeglądarce Internet Explorer (4-7) - do 2083 znaków

·         brak wbudowanej w ASP .NET infrastruktury umożliwiającej generowanie przyjaznych adresów URL

·         konieczność kodowania/dekodowania kluczy i wartości (jeśli zawierają niedozwolone znaki)

·         możliwość przekazania tylko ciągów znaków (konieczność konwersji na np. liczby)

 

Najlepsze zastosowanie:

·         przekazywanie jednej lub więcej par (nazwa=wartość)

·         przekazywanie identyfikatorów ze stron zawierających listy do stron ze szczegółami (widok master/detail)

Kilka słów o tyldzie (~)

W dalszej części artykułu wszystkie odnośniki poprzedzone są tyldą. Z punktu widzenia standardów internetowych nie są one poprawne, ale podczas generowania strony adresy te są przekształcane do poprawnej postaci.

Skąd ta decyzja? Każdy z czytelników podczas przeglądania stron internetowych napotkał zapewne na niedziałające odnośniki. Znaczna część tych problemów związana jest ze stosowaniem bezwzględnych lub względnych adresów.

 

Adresy względne

Aby wyświetlić obraz, który znajduje się w tym samym katalogu co strona html czy aspx wystarczy w kodzie html/aspx wstawić znacznik:

<img src="image.jpg"></img>

 

Do komplikacji dochodzi, gdy chcemy zmienić położenie strony i przenieść ją do podkatalogu. Wraz ze zmianą położenia strony musimy zaktualizować wszystkie odnośniki:

<img src="../image.jpg"></img>

 

Adresy bezwzględne

Adresy bezwzględne na pierwszy rzut oka nie sprawiają problemów, w ramach całej witryny możemy używać jednego odnośnika (MyWebSite to nazwa katalogu wirtualnego):

<img src="/MyWebSite/image.jpg"></img>

 

Jeśli jednak projekt przeniesiemy na serwer hostingowy i będzie on dostępny pod adresem http://www.myswebite.pl/, to odnośniki staną się nieprawidłowe. Prezentowany wcześniej znacznik będziemy musieli zamienić na:

<img src="/image.jpg"></img>

 

Zastosowanie tyldy uwalnia nas od wszystkich tych problemów, deklaracja

<img src="~/image.jpg" runat="server"></img>

raz na zawsze rozwiązuje problem wyświetlania obrazu na dowolnej stronie (pod warunkiem, że jego położenie w ramach katalogu wirtualnego pozostanie bez zmian). Ponosimy jednak pewnie koszty: zwykłe kontrolki html muszą być deklarowane z atrybutem runat="server", inaczej adresy nie będą poprawnie generowane. Następuje także nieznaczne wydłużenie czasu przetwarzania strony (przy każdym jej odświeżeniu).

Przykład 1 – deklaracja kontrolki HyperLink z parametrem

<asp:HyperLink ID="hlNoCode" runat="server" NavigateUrl="~/URL_Params/Receiver.aspx?sort=desc" Text="Mój odnośnik"></asp:HyperLink>

Przykład 2 - przekierowania

Aby przekierować użytkownika do innej strony i jednocześnie przekazać do niej dane za pośrednictwem parametrów URL, wystarczy wykonać:

[Kod C#]
Response.Redirect("~/URL_Params/Receiver.aspx?sort=desc");

Przykład 3 – kodowanie parametrów

Niektóre znaki jak np. ‘ ’, ‘&’ nie mogą być użyte ani w nazwach ani w wartościach parametrów, ponieważ mogłyby utrudnić ich odczyt. W przypadku gdy nie mamy pewności czy są one poprawne (lub zawierają treści wpisane przez użytkownika), powinniśmy przekształcać je do bezpiecznej postaci za pomocą metody UrlEncode (klasa HttpServerUtility):

[Kod C#]

//hlEncoded - HyperLink

string baseUrl = "~/URL_Params/Receiver.aspx?";

hlEncoded.NavigateUrl = baseUrl + "param=" + Server.UrlEncode("sort=desc");


Przykład 4 – odbieranie parametrów i sprawdzanie ich istnienia

[Kod C#]

string value = Request.QueryString["key"];

if (value == null)

{

    //URL nie zawierał parametru ‘key’

}

else

{

    //URL zawiera parametr ‘key’

}


Przykład 5 – odbieranie liczby całkowitej

[Kod C#]

int id = 0;

string key = "user_id";

string value = Request.Params[key];

if (value != null && int.TryParse(value, out id))

{

    //ok, zmienna value zawiera liczbę

}

else

{

    //brak wartości lub nieprawidłowy format

}


Przykład 6 – odbieranie i dekodowanie wartości

[Kod C#]
string sortParam = Server.UrlDecode(Request.QueryString["sort"]);

Przykład 7 – tworzenie sparametryzowanych odnośników w GridView

Kontrolka GridView powinna posiadać kolumnę typu HyperLinkField:

<asp:HyperLinkField DataTextField="Name" DataNavigateUrlFields="ProductID" DataNavigateUrlFormatString="~/URL_Params/Details.aspx?productID={0}" />

 

Pod atrybut DataNavigateUrlFields podstawiamy nazwy kolumn, których wartości mają zostać wstawione do odnośnika (oddzielone przecinkami).

DataNavigateUrlFormatString określa format odnośnika, fragmenty {0}, {1}, …{n} zostają zastąpione wartościami kolejnych kolumn.

 

Przykładowy rezultat:

/URL_Params/Details.aspx?productID=1

Przykład 8 – tworzenie sparametryzowanych odnośników w GridView (wiele wartości)

<asp:HyperLinkField DataNavigateUrlFields="BirthDate,Bonus"                 DataNavigateUrlFormatString="~/URL_Params/Details.aspx?birthdate={0:d}&bonus={1}" Text="Młodsi pracownicy z większym bonusem" />

 

Przykładowy rezultat:

/URL_Params/Details.aspx?birthdate=1954-01-11&bonus=5000,0000

Przykład 9 – tworzenie sparametryzowanych odnośników w GridView, specjalne wartości i formatowanie

Wartości parametrów deklarowane w HyperLinkField możemy formatować w zależności od naszych potrzeb. Aby tego dokonać, w szablonie odnośnika musimy dostawić specyfikator formatu (pełna lista dla typów numerycznych, pełna lista dla dat).

Przykład (przedstawianie liczb całkowitych w postaci szesnastkowej):

 

<asp:HyperLinkField DataTextField="Name" DataNavigateUrlFields="ProductID" DataNavigateUrlFormatString="~/URL_Params/Details.aspx?productID={0:x}" />

 

W przypadku dat zabieg ten jest wręcz wymagany (jeśli tego nie zrobimy, wygenerowane zostaną odnośniki bez atrybutu href, nie zostanie też głoszony błąd), patrz przykład 8.

Przykład 10 – kodowanie parametrów URL w GridView

Specyfikatory formatu niestety nie pozwolą na wyeliminowanie z odnośników np. spacji. Jeśli w odnośniku chcemy wstawić wartości zapisane w bazie danych jako np. varchar i nie możemy zagwarantować ich poprawności z punktu widzenia specyfikacji URL, musimy kolumny HyperLinkField przekonwertować na szablon.

Aby tego dokonać wywołujemy okno GridView Tasks (rysunek 1) i klikamy Edit Columns.

 

1wiz

Rysunek 1

 

W oknie Fields (rysunek 2) wybieramy istniejące pole typu HyperLinkField i klikamy Convert this field into a TemplateField.

 

2wiz

Rysunek 2

 

Otrzymujemy w ten sposób szablon:

<asp:TemplateField>

    <ItemTemplate>

        <asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl='<%# Eval("UserName", "~/URL_Params/Receiver.aspx?user_name={0}") %>'

            Text='<%# Eval("UserName") %>'></asp:HyperLink>

    </ItemTemplate>

</asp:TemplateField>

 

Który należy przekształcić do poniższej postaci:

<asp:TemplateField>

    <ItemTemplate>

<asp:HyperLink ID="hl" runat="server" NavigateUrl='<%# "~/URL_Params/Receiver.aspx?user_name=" + HttpUtility.UrlEncode((string)Eval("UserName")) %>'

    Text='<%# HttpUtility.HtmlEncode((string)Eval("UserName")) %>'></asp:HyperLink>

    </ItemTemplate>

</asp:TemplateField>

 

Warto zauważyć, że wykorzystana jest metoda UrlEncode klasy HttpUtility a nie HttpServerUtility (powód: HttpServerUtility korzysta z metod klasy HttpUtility; statyczne metody poprawiają czytelność kodu).

Przykład 11 – kodowanie wartości parametrów URL w GridView i code-behind

Kod przedstawiony w poprzednim przykładzie działa, ale wiele osób może uznać go za mało elegancki i niezbyt czytelny. Jego jakość możemy poprawić dzięki rozdzieleniu deklaracji kontrolki HyperLink i kodu ustawiającego atrybut NavigateUrl:

 

<!—plik *.master, *.aspx lub *.ascx-->

<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# FormatNavigateUrl(Container) %>'

Text='<%# FormatUserName(Container) %>'></asp:HyperLink>

 

[Kod C#]

protected string FormatNavigateUrl(object o)

{

    string userName = DataBinder.Eval(o, "DataItem.UserName").ToString();

    string encodedUserName = HttpUtility.UrlEncode(userName);

    return string.Format("~/URL_Params/Receiver.aspx?user_name={0}", encodedUserName);

}

protected string FormatUserName(object o)

{

    string userName = DataBinder.Eval(o, "DataItem.UserName").ToString();

    return HttpUtility.HtmlEncode(userName);

}




Odnośniki wewnątrz kontrolek Repeater, DataList i ListView (.NET Framework 3.5)

Odnośniki te mają postać identyczną jak przedstawiono w przykładzie 10 i 11.

Ciasteczka

Ciasteczka (ang. cookies) to dodatkowe dane przesyłane między serwerem i przeglądarką podczas przeglądania stron internetowych. Umożliwiają one np. realizację sesji (protokół http jest bezstanowy) oraz śledzenie aktywności użytkowników odwiedzających naszą witrynę.

 

Ciasteczka podlegają specyficznym ograniczeniom:

·         maksymalny rozmiar to 4096 bajtów

·         maksymalna liczba ciasteczek przypisanych do konkretnego serwera to 20

·         przeglądarki przechowują do 300 ciasteczek

Aby uniknąć niepotrzebnych problemów, należy ograniczać liczbę oraz rozmiar ciasteczek wykorzystywanych w ramach naszych aplikacji.

 

Zalety:

·         dostęp do danych z poziomu skryptów

·         możliwość ograniczania widoczności danych do wybranej ścieżki

 

Wady:

·         podatne na ingerencję użytkownika

·         ich obsługa w przeglądarce może być wyłączona (np. z powodu zastosowania wysokiego poziomu zabezpieczeń)

·         zwiększają ilość przesyłanych danych między serwerem i klientem

·         nie pozwalają na przechowywanie złożonych obiektów (chyba że są one zapisane w formacie JSON)

 

Najlepsze zastosowanie:

·         przechowywanie informacji nie wpływających na ogólne działanie witryny (np. preferencje)

·         monitorowanie wizyt anonimowych użytkowników

Przykład 1 – wykrywanie ciasteczka

Ciasteczka są identyfikowane za pomocą nazwy (w dalszych przykładach będzie to wartość „userData” lub zmienna cookieName):

[Kod C#]

const string cookieName = "userData";

//...

bool cookieExists = false;

if (Request.Cookies[cookieName] != null)

{

    cookieExists = true;

}


Przykład 2 – tworzenie ciasteczka

[Kod C#]

HttpCookie cookie = new HttpCookie(cookieName);

cookie.Expires = DateTime.MaxValue;

Response.Cookies.Add(cookie);


Właściwość Expires klasy HttpCookie określa termin ważności ciasteczka. Przedstawiony wcześniej kod ustawia maksymalny czas życia, oto alternatywy:

·         sesyjne ciasteczko: cookie.Expires = DateTime.MinValue;

·         termin ważności - dwa dni: cookie.Expires = DateTime.Now.AddDays(2);

 

Ciasteczka, których czas ważności został przekroczony, zostają automatycznie usunięte przez przeglądarki.

Przykład 3 – pobieranie wartości

Ciasteczko może przechowywać jedną bądź wiele wartości (zapisywanych podobnie jak parametry URL). Możemy je odczytać w następujący sposób:

[Kod C#]

//1 wartość w ciasteczku

string val1 = Request.Cookies[cookieName].Value;

 

//wiele wartości w ciasteczku

string val2 = Request.Cookies[cookieName]["klucz"];


Przykład 4 – ustawianie i zmiana wartości

Modyfikacja zawartości ciasteczek niesie ze sobą kilka problemów:

·         przeglądarki nie odsyłają daty ważności ciasteczka, modyfikacja ciasteczka wymaga zatem jej ponownego ustawienia (inaczej utworzone zostanie sesyjne ciasteczko)

·         API umożliwiające zarządzanie ciasteczkami „promuje” całkowite nadpisywanie ciasteczek (a nie zawsze nam o to chodzi)

 

Ustawianie/modyfikacja zawartości ciasteczka (gdy przechowujemy tylko jedną wartość):

[Kod C#]

string key = txtKey.Text.Trim();

string value = txtValue.Text;


HttpCookie cookie = Request.Cookies[cookieName];

cookie.Value = value;

//resetowanie 'terminu ważności':

cookie.Expires = DateTime.MaxValue;

Response.Cookies.Add(cookie);


Tworzenie osobnego ciasteczka dla każdej przechowywanej zmiennej nie jest efektywne ze względu na narzuty pojawiające się w komunikacji między klientem i serwerem. Znacznie lepiej jest w jednym ciasteczku przechować kilka wartości, są one zapisywane podobnie jak parametry URL.

Poniższy kod prezentuje ustawienie/modyfikację jednej z wartości ciasteczka:

[Kod C#]

string key = txtKey.Text.Trim();

string value = txtValue.Text;

//faktyczna modyfikacja

HttpCookie cookie = Request.Cookies[cookieName];

cookie[key] = value;

//resetowanie 'terminu ważności':

cookie.Expires = DateTime.MaxValue;

Response.Cookies.Add(cookie);



W następujący sposób usuniemy jedną z wartości przechowywanych w ciasteczku:

[Kod C#]

string key = txtRemoveKey.Text.Trim();

HttpCookie cookie = Request.Cookies[cookieName];

cookie.Values.Remove(key);

//resetowanie 'terminu ważności':

cookie.Expires = DateTime.MaxValue;

Response.Cookies.Add(cookie);



Niestety podobnie jak w przypadku parametrów URL, wprowadzenie dodatkowych znaków & może utrudnić odczytanie i przetwarzanie ciasteczka. W przypadku gdy nie mamy wpływu na dane zapisywane do ciasteczek, powinniśmy stosować identyczne podejście jak w przypadku kodowania parametrów URL:

[Kod C#]

//dodawanie/ustawianie wartości

string key = txtKey.Text.Trim();

string value = txtValue.Text;

key = Server.UrlEncode(key);

value = Server.UrlEncode(value);

HttpCookie cookie = Request.Cookies[cookieName];

cookie[key] = value;

//resetowanie 'terminu ważności':

cookie.Expires = DateTime.MaxValue;


Przykład 5 – usuwanie ciasteczka

Ciasteczka usuwamy poprzez zmianę daty wygaśnięcia na wsteczną a następnie dodanie go do kolekcji Response.Cookies:

[Kod C#]

HttpCookie cookie = Request.Cookies[cookieName];

if (cookie == null)

{

    return;

}

cookie.Expires = DateTime.Now.AddHours(-1);

Response.Cookies.Add(cookie);


Uwaga: jeśli pod datę wygaśnięcia podstawimy minimalną wartość (DateTime.MinValue), wówczas ciasteczko nie będzie usunięte, lecz stanie się ciasteczkiem sesyjnym (są usuwane z pamięci po zamknięciu przeglądarki).

Więcej przykładów dotyczących ciasteczek w ASP .NET zamieszczono w artykule ASP .NET Cookies Overview (MSDN).

Przekierowania po stronie serwera

Przekierowania po stronie serwera pozwalają na przeniesienie użytkownika do nowej strony, ale bez tworzenia dodatkowych połączeń między klientem a serwerem. Dodatkowo przekierowania te pozwalają na przekazanie dowolnych danych między dwoma stronami.

 

Zalety:

·         brak obciążenia klienta i pasma, nie są tworzone nowe połączenia z serwerem

·         możliwość przekazywania parametrów URL, wartości kontrolek oraz złożonych obiektów

·         niejawność przekazywanych danych

 

Wady:

·         nie można dokonać przekierowania do innej witryny (np. microsoft.com)

·         użytkownik nie jest informowany o przejściu do innej strony, pasek adresu w przeglądarce pozostaje bez zmian (co może powodować kłopoty np. przy dodawaniu strony do „ulubionych”)

 

Najlepsze zastosowanie:

·         złożone formularze, które muszą zostać podzielone na wiele kroków

Przykład 1 – przekierowanie

Przekierowania po stronie serwera są równie proste w użyciu jak „zwykłe” przekierowania:

[Kod C#]
Server.Transfer("~/OtherPage.aspx");

Możemy przy tym określić jak dużo informacji będzie przekazanych do kolejnej strony. Następujące wywołanie spowoduje, że do kolejnej strony nie zostaną przekazane parametry URL i dane przesyłane przez klienta w trakcie postbacku (dostępne poprzez Request.Form):

[Kod C#]
Server.Transfer("~/OtherPage.aspx", /*preserveForm*/ false);

Przykład 2 – wykrywanie przekierowań

[Kod C#]

//czy doszło do przekierowania?

if (PreviousPage != null && !PreviousPage.IsCrossPagePostBack)

{

    //tak

}

else

{

    //nie

}


Przykład 3 – przekazanie wartości kontrolek

Bez zastosowania stron wzorcowych, dostęp do kontrolek z poprzedniej strony uzyskamy za pomocą metody FindControl:

[Kod C#]

if (PreviousPage.Master == null)

{

    TextBox txtName = (TextBox)PreviousPage.FindControl("txtName");

    lblName.Text = txtName.Text;

}


               

Powyższy warunek nie jest wymagany, ale pozwala zabezpieczyć się przed błędem w przypadku, gdy poprzednia strona jest skojarzona z dowolną stroną wzorcową.

Przykład 4 – przekazywanie wartości kontrolek a strony wzorcowe

W przypadku przekierowań ze stron opartych o strony wzorcowe, musimy najpierw pobrać referencję do odpowiedniego ContentPlaceHolder’a. Jego identyfikator jest „zaszyty” w pliku *.aspx:

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="Server">

oraz w pliku *.master:

<asp:contentplaceholder id="MainContent" runat="server">

</asp:contentplaceholder>

Oto kod przedstawiający pobranie pola tekstowego z poprzedniej strony:

[Kod C#]

if (PreviousPage.Master != null)

{

    ContentPlaceHolder cph = (ContentPlaceHolder)PreviousPage.Master.FindControl("MainContent");

    TextBox txtName = (TextBox)cph.FindControl("txtName");

    lblName.Text = txtName.Text;

}


Przykład 5 – przekazywanie wartości kontrolek a walidacja

Samo wykorzystanie walidatorów nie gwarantuje, że po postbacku kontrolki będą zawierały prawidłowe dane. Użytkownik zawsze może wyłączyć obsługę skryptów w przeglądarce, zatem niezbędne jest sprawdzenie poprawności strony:

[Kod C#]

if (!Page.IsValid)

{

    return; //błąd walidacji

}


W przypadku przekierowań po stronie serwera nie zawsze możemy mieć pewność, że dane zawarte na poprzedniej stronie są poprawne. Możemy jednak to sprawdzić:

[Kod C#]

if (!PreviousPage.IsValid)

{

    return; //strona niepoprawna

}


Przykład 6 – odbieranie parametrów URL

Dostęp do parametrów URL na stronie, do której przekierowaliśmy użytkownika odbywa się tych samych zasadach bez względu na to czy wystąpiły przekierowania czy nie.

Warto wspomnieć, że adres strony pozostaje bez zmian także z poziomu ASP .NET. Po przekierowaniu z Default.aspx na OtherPage.aspx, właściwość Request.RawUrl zwraca adres poprzedniej strony: /ST/Transfer/Default.aspx. Zmienia się jedynie wartość Request.CurrentExecutionFilePath: /ST/Transfer/OtherPage.aspx.

Przykład 7 – przekazywanie zmiennych i złożonych obiektów

Na dłuższą metę bezpośredni dostęp do kontrolek poprzedniej strony jest uciążliwy, zwiększa zależności między stronami i ryzyko powstania błędów (choćby przez zmianę identyfikatora kontrolki). Oto trzy możliwe rozwiązania tego problemu:

a) intefejs

Jest to najbardziej elastyczne rozwiązanie, gdyż działa poprawnie we wszystkich typach projektów, oraz pozwala na szybką weryfikację czy przekierowanie nastąpiło z „właściwej” strony.

Tworzymy interfejs, wraz z właściwościami/metodami umożliwiającymi przekazanie danych (w tym przypadku tylko Guid):

[Kod C#]

public interface IGuidHolder

{

    Guid GeneratedValue { get; }

}


Następnie zmieniamy deklarację strony źródłowej (z której dokonamy przekierowania) tak, by implementowała nowy interfejs:

[Kod C#]

public partial class Transfer_Default : System.Web.UI.Page, IGuidHolder

{

    public Guid GeneratedValue

    {

        get { return new Guid(txtGuid.Text); }

    }

}


Poniższy kod prezentuje sposób w jaki możemy odebrać guida z poprzedniej strony:

[Kod C#]

if (PreviousPage == null)

{

    lblResult.Text = "brak poprzedniej strony";

    return;

}

if (!(PreviousPage is IGuidHolder))

{

    lblResult.Text = "przekierowanie z niewłaściwej strony!";

    return;

}

IGuidHolder holder = (IGuidHolder)PreviousPage;

lblResult.Text = string.Format("odebrano wartość: {0}", holder.GeneratedValue);


b) silnie typowana „poprzednia strona”

Wykorzystanie interfejsów czy wielokrotne rzutowanie właściwości PreviousPage może być na dłuższą metę kłopotliwe. Istnieje na szczęście sposób stworzenia silnie typowanej „poprzedniej strony”.

Do kodu strony wystarczy dodać dyrektywę ze ścieżką do wybranej strony:

<%@ PreviousPageType VirtualPath="~/Transfer/Default.aspx" %>

 

Lub z nazwą jej klasy bazowej (uwaga: wybrany typ musi dziedziczyć po klasie Page):

<%@ PreviousPageType TypeName="BasePage" %>

 

Od tej pory nie musimy już rzutować PreviousPage na wybrane typy.

 

c) publiczne właściwości/metody (bez interfejsów)

W tym przypadku pomijamy interfejs i odwołujemy się bezpośrednio do instancji określonej klasy. Podejście to należy stosować tylko gdy nie chcemy tworzyć dodatkowych interfejsów i przekierowania mogą nastąpić z kilku różnych stron.

Dla projektu typu Web Site dostęp do typu innej strony/kontrolki uzyskamy jedynie przez dodanie do strony dyrektywy:

 

<%@ PreviousPageType VirtualPath="~/Transfer/Default.aspx" %>

 

W projektach typu Web Application (ze względu na inną strukturę i proces kompilacji) nie jest to wymagane.

Poniższy kod jest podobny do prezentowanego w punkcie 7a), lecz interfejs zastąpiony jest określonym typem:

[Kod C#]

if (!(PreviousPage is Transfer_Default))

{

    lblResult.Text = "przekierowanie z niewłaściwej strony!";

    return;

}

IGuidHolder holder = (Transfer_Default)PreviousPage;

lblResult.Text = string.Format("odebrano wartość: {0}", holder.GeneratedValue);


Cross-Page Posting

Cross-Page Posting (CPP) to nowość w ASP .NET 2.0. Pozwala w relatywnie prosty sposób wysłać dane wpisane w formularzu do innej strony.

W aplikacjach ASP .NET 1.1 kliknięcie przycisku prowadziło do przesłania danych za pomocą metody POST pod ten sam adres z którego strona ta została wygenerowana. Zmiana atrybutu action dla elementu form wymagała stosowania własnej kontrolki dziedziczącej po HtmlForm.

CPP eliminuje te ograniczenia i pozwala m.in. na to, aby dane były przekazywane do różnych stron w zależności od klikniętego przycisku.

 

Kontrolki, które mogą wywołać CPP muszą implementować interfejs IButtonControl, czyli dotyczy to klas:

·         Button

·         LinkButton

·         ImageButton

 

Funkcjonalność CPP została częściowo zrealizowana przy pomocy skryptów JavaScript (zachowano przy tym kompatybilność z najpopularniejszymi przeglądarkami).

 

Zalety:

·         przesyłanie danych nie jest ograniczone do bieżącej aplikacji

·         zmiana adresu URL jest widoczna (w przeciwieństwie do przekierowań po stronie serwera)

·         relatywnie prosty sposób na przesłanie zawartości formularza metodą POST

  

Wady:

·         rozwiązanie oparte o JavaScript

 

Najlepsze zastosowanie:

·         realizacja e-płatności i przekazywanie dużej ilości danych do innych witryn bez możliwości stosowania usług internetowych (ang. web services).

Poniższy schemat ilustruje kolejność wywoływania zdarzeń na stronie źródłowej i docelowej podczas CPP.

Strona źródłowa

Strona docelowa

<start>

PreInit

Init

InitComplete

PreLoad

Load

<obsługa kliknięcia przycisku>

LoadComplete

Unload

<koniec>

<start>

PreInit

Init

InitComplete

PreLoad

Load

LoadComplete

PreRender

PreRenderComplete

SaveStateComplete

Unload

<koniec>

Widzimy, że nie zachodzą wszystkie zdarzenia związane z „cyklem życia” strony źródłowej. Do momentu wywołania LoadComplete zachowany jest porządek, jednak potem wywołane zostaje jedynie zdarzenie Unload.

Przykład 1 – deklaracja przycisku

Pod atrybut PostBackUrl wystarczy podstawić adres docelowej strony:

<asp:Button ID="btnFirst" Text="Prześlij do First.aspx" PostBackUrl="~/CPP/First.aspx" runat="server" />

Przykład 2 – wykrywanie CPP

Właściwość IsCrossPagePostBack pozwala na odróżnienie czy mamy do czynienia z przekierowaniem po stronie serwera czy CPP, gdyż w obu przypadkach właściwość PreviousPage zwraca referencję do poprzedniej strony.

Jeśli dla aktualnej strony zachodzi IsCrossPagePostBack==true, wówczas oznacza to, że mamy do czynienia ze źródłową stroną.

Jeśli zachodzi PreviousPage.IsCrossPagePostBack==true, to znaczy, że mamy do czynienia ze stroną docelową, która może odebrać dane ze strony poprzedniej.

Przykład 3 – pobieranie danych przesłanych przy pomocy CPP

Pobieranie danych przesłanych przy pomocy CPP odbywa się na takich samych zasadach jak odbieranie danych przesłanych poprzez przekierowania po stronie serwera:

·         przekazanie wartości kontrolek

·         przekazywanie wartości kontrolek a strony wzorcowe

·         przekazywanie wartości kontrolek a walidacja

·         przekazywanie zmiennych i złożonych obiektów

Sesja

Dla każdego użytkownika aplikacji ASP .NET tworzona jest osobna sesja, która (przy domyślnych ustawieniach) wygasa po 20 minutach nieaktywności użytkownika. W przypadku gdy sesja działa w trybie InProc (domyślny), wówczas możemy umieszczać w niej dowolne obiekty. W pozostałych przypadkach (StateServer i SQLServer) obiekty muszą być oznaczone atrybutem SerializableAttribute.

 

Zalety:

·         nie obciąża ani klienta ani pasma

·         niejawność przekazywanych informacji

 

Wady:

·         duża liczba (lub rozmiary) przechowywanych obiektów w sesji prowadzi do spowolnienia aplikacji

·         dane dostępne są dla wszystkich stron

 

Najlepsze zastosowanie:

·         przechowywanie danych dotyczących określonego użytkownika podczas jego interakcji z aplikacją

·         przekazywanie złożonych obiektów między stronami w przypadku, gdy nie można użyć mechanizmu cross-page posting oraz przekierowań po stronie serwera

Przykład 1 – wstawianie nowych danych

[Kod C#]

MyData myData = new MyData();

Session["data"] = myData;


Przykład 2 – pobieranie danych

[Kod C#]

if (Session["data"] != null)

{

MyData myData = (MyData)Session["data"];

}


Przykład 3 – usuwanie danych

[Kod C#]
Session["data"] = null;

Inne (cache, stan aplikacji)

Dane możemy również przekazywać za pośrednictwem cache’u (klasa Cache) czy stanu aplikacji (klasa HttpApplicationState). Musimy się jednak liczyć z tym, że składowane w nich informacje są dostępne dla wszystkich sesji. Są one przez to niepraktyczne w kontekście przekazywania danych między stronami, gdyż wymagają od nas generowania złożonych kluczy i w ten sposób duplikujemy funkcjonalność oferowaną przez sesję.

Podsumowanie

+ => tak; - => nie

Parametry URL

Ciasteczka

Przekierowania po stronie serwera

Cross-Page Posting

Sesja

Jawność przekazywanych danych

+

+

-

*

-

Możliwość ingerencji ze strony użytkownika

+

+

-

+/-

(zaawansowani użytkownicy)

-

Przekazywanie złożonych obiektów

-

-

+

+

(tylko w ramach tej samej aplikacji)

+

Dostęp do danych z poziomu skryptów JavaScript

+

+

-

-

-

Wymagana przeglądarka z obsługą języka JavaScript

-

-

-

+

-

Obciąża pasmo

+/-

(zależy od liczby parametrów)

+

-

-

-

Obciąża serwer

+

(nieznacznie – odnośniki z tyldą)

-

-

-

+

Wpływ na usability

pozytywny

negatywny

(nie można dodać docelowej strony do „ulubionych”)

negatywny

(jeśli przeglądarka nie obsługuje skryptów JavaScript)

Inne

zalecana maksymalna długość odnośnika to 2083 znaki

maksymalny rozmiar - 4096 bajtów.

Maksymalna liczba ciasteczek przypisanych do konkretnego serwera to 20.

Przeglądarki przechowują do 300 ciasteczek

Mogą wystąpić błędy po zmianie trybu sesji

* -  dane zawarte w formularzu można przechwycić (chyba że transmisja będzie się odbywać za pośrednictwem szyfrowanego połączenia). Nie można jednak uzyskać dostępu do danych przekazywanych za pośrednictwem właściwości i metod poprzedniej strony.

 

W przykładach dołączonych do projektu wykorzystana została baza danych AdventureWorks.

Literatura

Dino Esposito - Validating ASP.NET Query Strings

Dino Esposito – Programming Microsoft ASP .NET 2.0 Core Reference, Microsoft Press

ASP .NET Cookies Overview (MSDN).

Załączniki:

Podobne artykuły

Komentarze 0

pkt.

Zaloguj się lub Zarejestruj się aby wykonać tę czynność.