Nawet
najlepiej napisana i najbezpieczniejsza aplikacja internetowa może odmówić
prawidłowego działania w określonych warunkach. Aplikacja może „wywrócić się”
pod wpływem nieumyślnego bądź też celowego działania użytkownika, niepoprawnie
skonfigurowanego serwera lub też po prostu z powodu nie przewidzenia przez
programistę zachowania aplikacji w określinych sytuacjach. Ważną sprawą jest
obsługa przez aplikację opisanych wyżej sytuacji. Języki programowania
działające na platformie .NET mają możliwość obsługiwania tak zwanych wyjątków
– czyli najprościej mówiąc nie przewidywanych przez twórców programu,
„wyjątkowych” sytuacji.
Wyobraźmy
sobię sytuację, w której przy załadowaniu strony internetowej nasza aplikacja
próbuje wyświetlić, odczytane uprzednio z pliku tekstowego informacje. Otwarcie
pliku odbywać się będziew metodzie Page_Load.
protected
void Page_Load(object
sender, EventArgs e)
{
System.IO.FileStream fs = System.IO.File.Open(@"c:\plik",
System.IO.FileMode.Open);
}
Podana
w aplikacji ścieżka dostępu do pliku może być jednak nieprawidłowa, co może być
spowodowane usunięciem pliku, brakiem uprawnień do jego odczytu, bądź też
zwykłą pomyłką programistów lub osób wdrażających aplikację na serwerze. W
opisanej wyżej sytuacji zamiast zawartości naszej formatki, w oknie
przeglądarki internetowej ujrzymy następującą informację:

Nie
chcemy oczywiście, aby tego typu informacje ukazywały się użytkownikom naszej
aplikacji. Mogą one posłużyć rozmaitym intruzom lub włamywaczom do zdobycia
informacji na temat środowiska zainstalowanego na serwerze, natomiast
„zwyczajnych użytkowników sieci” będą po prostu niepokoić i irytować.
Wyjątki
możemy obsługiwać w prosty sposób używając do tego celu programowej
konstrukcji: try – catch – finally. Jej działanie zaprezentujmy na przykładzie
naszej formatki. Zmodyfikujmy zawartość metody Page_Load w następujący sposób:
protected
void Page_Load(object
sender, EventArgs e)
{
try
{
System.IO.FileStream fs = System.IO.File.Open(@"c:\plik",
System.IO.FileMode.Open);
}
catch
{
Response.Write("Wystąpił błąd. Nie można
odczytać pliku źródłowego");
}
}
Tym
razem po otwarciu strony w oknie przeglądarki ukaże się następujący widok:

Przeanalizujmy
jak do tego doszło. Otóż każdy kod, mogący powodować błędy w działaniu
aplikacji (w naszym przypadku będzie to próba otwarcia nieistniejącego w pliku)
powinien znajdować się w klazuli „Try”. W momencie wystąpienia wyjątku,
działanie kodu zostaje przerwane i aplikacja przechodzi do wykonywania
instrukcji zawartej w klauzuli catch. W naszym przypadku program próbuje
otworzyć nieistniejący plik. W momencie, kiedy wykonanie tej systuacji okazuje
się niemożliwe, rozpoczyna się wykonywanie kodu obsługującego wyjątek. W
przypadku naszej aplikacji będzie to wypisanie na standartowe wyjście
odpowiedniej informacji. Używając tej klauzuli możemy również przechwytywać
specyficzne rodzaje wyjątkowych sytuacji. Poniższy kod prezentuje przechwycenie
wyjątku związanego z operacjami wejścia-wyjścia i wyświetlenia szczegółowej
informacji na ten temat:
protected
void Page_Load(object
sender, EventArgs e)
{
try
{
System.IO.FileStream fs = System.IO.File.Open(@"c:\plik",
System.IO.FileMode.Open);
}
catch (System.IO.FileNotFoundException
ex)
{
Response.Write("Wystąpił błąd: " +
ex.Message);
}
}
W
powyższym kodzie nie występuje ostatnia część kodu umożliwiającego obsługę
błędów, tzn. Dyrektywa: „Finally”. Umieszczamy ją zazwyczaj na koniec podobnych
do powyższej instrukcji i zamieszczamy tam kod, który będzie wykonywany bez
względu na prawidłowy lub niepoprawny przebieg operacji.
try
{
...
}
catch
{
...
}
finally
{
objConnection.Close();
}
W
powyższym przykładzie bez względu na wystąpienie wyjątku połączenie o nazwie
objConnection zostanie zakończone.
Języki
działające na platformie .NET, takie jak Visual Basic czy C# dają programistom
możliwość wyłapywania specyficznych rodzajów wyjątków. Kilka przykładowych
błedów, które może „pochwalić się” posiadaniem zdefiniowanych przez twórców
tych języków wyjątków to błąd przepełnienia bufora, upłynięcia określonego
czasu oczekiwania, czy błąd nieautoryzowanego dostępu. Twórców aplikacji
internetowych szczególnie interesują wyjątki, związane w systuacjami mogącymi
wystąpić w trakcie działania witryn, pisanych w technologii ASP.NET.
Przechwycenia
określonego wyjątku i wyświetlenie informacji związanej z tym wyjątkiem,
dokonuje się w następujący sposób.
try
{
}
catch(Exception
ex)
{
this.response.write(„Wystąpił błąd: „ +
ex.Message);
}
Zastosowanie
takiego kodu na stronie, powodującej wystąpienie błędu, może zaowocować
przedstawionym poniżej rezultatem.

Możemy
zapewnić również naszej aplikacji globalną obsługę błędów. W tym celu dodajemy
do naszego projektu plik Web.config (Website -> Add New Item -> Web
Confguration File), a następnie dodajemy do niego następujące linie (uwaga –
muszą być one umieszczone między znacznikami
<system.web></system.web>. Domyślnie przykładowe linie tego typu
będą już się tam znajdować, tyle że będą zakomentowane.
<customErrors
mode="On"
defaultRedirect="GenericErrorPage.htm">
<error
statusCode="403"
redirect="NoAccess.htm"/>
<error
statusCode="404"
redirect="FileNotFound.htm"/>
</customErrors>
Poniższy
plik konfiguracyjny zawiera obsługę standartowych błędów 403 i 404. W przypadku
pojawienia się tych błedów nastąpi przekierowanie na zdefiniowane w pliku
konfiguracyjnym strony. Domyślną stroną, na którą będzie następowało
przekierowanie w przypadku wystąpienia innych sytuacji będzie „GenericErrorPage.htm”.
W poniższej tabeli zamieszczam kilka najpopularniejszych kodów wraz z krótkimi
opisami.
|
Kod
|
Opis
|
|
400
|
Format
zapytania otrzymanego przez serwer jest niepoprawny.
|
|
401
|
Osoba
nie ma odpowiednich uprawnień do oglądania zawartości strony
|
|
403
|
Serwer
odmawia wykonania żądania
|
|
404
|
Szukana
strona nie została odnaleziona na serwerze.
|
|
408
|
Przekroczony
został czas oczekiwania na odpowiedź serwera
|
|
500
|
Wewnętrzny
bład serwera. Kod ten reprezentuje wszystkie nieobsługiwane wyjątki w
aplikacjach działających na serwerze
|
|
503
|
Usługa
jest chwilowo niedostępna
|
|
505
|
Wersja
protokołu HTTP, używana przez klienta, jest nieobsługiwana przez serwer.
|
Możemy
również definiować obsługę błędów na poziomie poszczególnych plików *.aspx. W
tym celu w rozpoczynającej stronę dyrektywie „<%@Page...%>” dodajemy
właściwość o nazwie: errorPage.
<%@
Page Language="C#"
AutoEventWireup="true"
CodeFile="Default.aspx.cs"
Inherits="_Default"
ErrorPage ="~/ErrDefault.aspx"
%>
W
momencie wystąpienia nieobsługiwanego wyjątku, nastąpi przekierowanie na stronę
ErrDefault.aspx