Artykuł pochodzi w serii przygotowań do egzaminu 70-562 ASP.NET.
Tworząc aplikacje internetowe istnieje kilka scenariuszy, które różnią się od typowego scenariusza żądanie – obsługa żądania. Przykładem takich scenariuszy może być łapanie wyjątków na poziomie całej strony lub całej aplikacji, wykonywanie zadań asynchronicznie, tworzenie specyficznych handlerów dla protokołu HTTP.
Dzisiejszy artykuł będzie właśnie opisywał tego typu scenariusze.
Wyjątki na poziomie aplikacji oraz strony
Tworząc aplikacji programiści wykorzystują wyjątki oraz bloki try-catch do obsługi sytuacji wyjątkowych. Aby obsługa ta była efektywna w bloki try-catch powinno się obejmować jak najmniejsze fragmenty kodu. Takich przykładem może być fragment kodu, w którym następuje połączenie do bazy danych i wyciągnięcie z niej informacji. Jednakże programista na ogól nie jest w stanie lub nie opłaca mu się to, aby tworzyć kod dla wszystkich możliwych do wyrzucenia wyjątkach. Dlatego ASP.NET umożliwia wyłapywanie wyjątków na poziomie całej strony lub całej aplikacji.
W celu wyłapania wszystkich wyjątków występujących na danej stronie, które nie zostały obsłużone wystarczy dodać do kodu strony metodę Page_Error, która może wyglądać następująco:
1: protected void Page_Error(object sender, EventArgs e)
2: {
3: var error = Server.GetLastError(); //wyciągnięcie ostatniego błędu
4: string message = error.Message;
5: Server.ClearError(); //wyczyszczenie listy błędów
6: Response.Write("Nieoczekiwany błąd: " + message); //wyświetlenie komunikatu
7: }
Co ważne, informacje o nieobsłużonym wyjątku musimy wyciągnąć za pomocą metody
GetLastError właściwości
Server klasy
Page. Mając już wyjątek jaki wystąpił, możemy coś z nim zrobić (np. wyświetlić użytkownikowi informację o błędzie). Na koniec warto jeszcze wyczyścić listę błędu, które wystąpiły za pomocą metody
ClearError właściwości Server. Z poziomu metody Page_Error programista nie ma dostępu do kontrolek znajdujących się na stronie.
ASP.NET umożliwia również wyłapywanie nieobsłużonych wyjątków na poziomie samej aplikacji. Aby dodać obsługę wystarczy dodać do klasy Global znajdującej się w pliku Global.asax metodę Application_Error, która może wyglądać następująco:
1: protected void Application_Error(object sender, EventArgs e)
2: {
3: //kod wykonany, gdy nastąpił nieobslużony wyjątek
4: Server.Transfer("HandleError.aspx");
5: }
Podobnie jak w przypadku wyłapywaniu wyjątków na poziomie pojedynczej strony mamy dostęp do właściwości Server.
Dostęp do pliku Web.config
ASP.NET udostępnia również możliwość z programowego dostępu do pliku Web.config, w którym znajduje się konfiguracja aplikacji. W tym celu trzeba skorzystać z klasy WebConfigurationManager znajdującej się w przestrzeni nazw System.Web.Configuration. Aby odczytać jakąś sekcje z pliku konfiguracyjnego, wywołujemy metodę GetSection klasy WebConfigurationManager i przekazujemy do niej sekcje jaką chcemy odczytać. Co ważne, metoda ta zwraca typ object, dlatego musimy jeszcze zrzutować na odpowiedni typ związany z daną sekcją. Poniżej przykład kod, za pomocą którego można odczytać tryb uwierzytelniania.
1: AuthenticationSection section =
2: (AuthenticationSection) WebConfigurationManager.GetSection("system.web/authentication");
3:
4: string mode = section.Mode.ToString();
Klasa WebConfigurationManager umożliwia również odczytywanie ustawień aplikacji zdefiniowanych przez programistę w pliku konfiguracyjnym. Wystarczy skorzystać z właściwości AppSettings, jak to widać niżej na przykładzie:
1: string mySetting = WebConfigurationManager.AppSettings["MySetting"];
Również klasa ta umożliwia łatwe odczytanie connection stringa z pliku Web.config. Wystarczy skorzystać z właściwości ConnectionStrings:
1: string connectionString = WebConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
Klasa WebConfigurationManager bardzo dobrze nadaje się do odczytywania ustawień aplikacji, już gorzej jest z zapisywaniem nowych ustawień. W celu zmiany ustawień i zapisania powinno skorzystać się z klasy Configuration z przestrzeni nazw System.Configuration.
W celu zmiany konfiguracji wywołujemy metodę OpenWebConfiguration klasy WebConfigurationManager, która właśnie zwraca obiekt klasy Configuration. Następnie za pomocą metody GetSection wyciągamy odpowiednią sekcję z pliku. Zmieniamy właściwości i na koniec wywołujemy metodę Save obiektu klasy Configuration. Najlepiej to zobaczyć na przykładzie:
1: Configuration configuration = WebConfigurationManager.OpenWebConfiguration(null);
2: AuthenticationSection authenticationSection = (AuthenticationSection)configuration.GetSection("system.web/authentication");
3: authenticationSection.Mode = AuthenticationMode.Forms;
4: configuration.Save();
Natomiast, aby zapisać plik konfiguracyjnym w innym miejscu wystarczy wywołać metodę SaveAs i przekazać do niej nową lokalizację pliku.
HTTP Handler
HTTP Handler jest kodem, który jest wykonywany w przypadku żądania HTTP do serwera dla określonego zasobu. Przykładowym HTTP handlerem jest ASP.NET page handler, który jest uruchamiany, gdy do serwera przyjdzie żądanie od pliku *.aspx.
Programista może dodawać do aplikacji webowej swoje własne handlery, w celu wykonywania kod specyficznego dla danego typu zasobu. Takim przykładowym handlerem może być handler, który generuje obrazki z ciągiem znaków, który może posłużyć za mechanizm zabezpieczający formularz przed wysyłaniem zbędnych wiadomości.
Aby stworzyć swój własny handler wystarczy do projektu dodać klasę, która implementuje interfejs IHttpHandler. Implementując ten interfejs musimy zaimplementować jedną właściwość (IsReusable) oraz jedną metodę (ProcessRequest).
Właściwość IsReusable informuje ASP.NET, czy instancje handlera mogą być wykorzystywane kilkakrotnie, czy dla każdego nowego żądania powinien być tworzony od nowa handler.
Natomiast metoda ProcessRequest wykonuje właściwy kod dla danego żądania do zasobu. Przykładowa implementacja może wyglądać następująco:
1: public class ImageHttpHandler : IHttpHandler
2: {
3: #region IHttpHandler Members
4:
5: public bool IsReusable
6: {
7: get { return false; }
8: }
9:
10: public void ProcessRequest(HttpContext context)
11: {
12: context.Response.ContentType = "image/jpeg";
13: Image image = CreateImage();
14: context.Response.Write(image);
15: }
16:
17: private Image CreateImage()...
18:
19: #endregion
20: }
Na koniec wystarczy do pliku Web.config do sekcji system.web dodać informacje o handlerze oraz zasobie, do jakiego ma być wywoływany handler:
1: <httpHandlers>
2: <add verb="*" path="*.jpg" type="ImageHandler"/>
3: <add verb="*" path="*.gif" type="ImageHandler"/>
4: </httpHandlers>