Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00156 009727 11027762 na godz. na dobę w sumie
ASP.NET AJAX. Programowanie w nurcie Web 2.0 - książka
ASP.NET AJAX. Programowanie w nurcie Web 2.0 - książka
Autor: Liczba stron: 432
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-1494-3 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> webmasterstwo >> asp
Porównaj ceny (książka, ebook, audiobook).

Wykorzystaj najlepsze rozwiązania technologii AJAX i stwórz interaktywną stronę internetową

Zastanawiałeś się, dlaczego interaktywne witryny cieszą się dziś taką popularnością? Dzieje się tak głównie dlatego, że wymagają one od użytkowników współuczestnictwa w tworzeniu i rozwoju serwisu, a tym samym powodują, że abonenci mają duży wpływ na jego ostateczny kształt. Dzięki temu każdy odbiorca korzysta z atrakcyjnej witryny idealnie dopasowanej do swoich potrzeb. To właśnie ASP.NET AJAX umożliwia projektowanie profesjonalnych, interaktywnych stron WWW w duchu Web 2.0. Znawcy tematu zapewniają, że AJAX jest rozwiązaniem przyszłościowym w dziedzinie projektowania serwisów internetowych. O tym, jak za pomocą tej technologii wdrożyć w swoim serwisie rozwiązania zgodne z filozofią Web 2.0, dowiesz się właśnie z tego podręcznika.

W książce 'ASP.NET AJAX. Programowanie w nurcie Web 2.0' zamieszczono, oprócz teoretycznych wiadomości, mnóstwo przykładów demonstrujących działanie najważniejszych mechanizmów środowiska ASP.NET AJAX. Przedstawione rozwiązania mają bardzo ogólny charakter, a zatem możesz szybko dostosować je do potrzeb własnej aplikacji. Korzystając z tego podręcznika, nauczysz się m.in. projektować własne kontrolki i udostępniać je w serwisie Toolkit, poznasz zasady korzystania ze standardowych bibliotek AJAX-a w innych środowiskach (np. PHP). Będziesz umiał zbudować profesjonalną, dynamiczną stronę internetową, bazującą na platformie ASP.NET AJAX.

Płyń z nurtem nowoczesności -- twórz elektryzujące, interaktywne strony WWW!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

ASP.NET AJAX. Programowanie w nurcie Web 2.0 Autor: Christian Wenz T‡umaczenie: Marek Pa‡czyæski ISBN: 978-83-246-1494-3 Tytu‡ orygina‡u: Programming ASP.NET AJAX: Build rich, Web 2.0-style UI with ASP.NET AJAX Format: 168x237, stron: 432 Wykorzystaj najlepsze rozwi„zania technologii AJAX i stw(cid:243)rz interaktywn„ stronŒ internetow„ (cid:149) Jak wykorzystywa(cid:230) dane serwerowe? (cid:149) Jak tworzy(cid:230) i udostŒpnia(cid:230) w‡asne kontrolki? (cid:149) Jak aktualizowa(cid:230) czŒ(cid:156)(cid:230) strony w regularnych odstŒpach czasu? Zastanawia‡e(cid:156) siŒ, dlaczego interaktywne witryny ciesz„ siŒ dzi(cid:156) tak„ popularno(cid:156)ci„? Dzieje siŒ tak g‡(cid:243)wnie dlatego, ¿e wymagaj„ one od u¿ytkownik(cid:243)w wsp(cid:243)‡uczestnictwa w tworzeniu i rozwoju serwisu, a tym samym powoduj„, ¿e abonenci maj„ du¿y wp‡yw na jego ostateczny kszta‡t. DziŒki temu ka¿dy odbiorca korzysta z atrakcyjnej witryny idealnie dopasowanej do swoich potrzeb. To w‡a(cid:156)nie ASP.NET AJAX umo¿liwia projektowanie profesjonalnych, interaktywnych stron WWW w duchu Web 2.0. Znawcy tematu zapewniaj„, ¿e AJAX jest rozwi„zaniem przysz‡o(cid:156)ciowym w dziedzinie projektowania serwis(cid:243)w internetowych. O tym, jak za pomoc„ tej technologii wdro¿y(cid:230) w swoim serwisie rozwi„zania zgodne z filozofi„ Web 2.0, dowiesz siŒ w‡a(cid:156)nie z tego podrŒcznika. W ksi„¿ce (cid:132)ASP.NET AJAX. Programowanie w nurcie Web 2.0(cid:148) zamieszczono, opr(cid:243)cz teoretycznych wiadomo(cid:156)ci, mn(cid:243)stwo przyk‡ad(cid:243)w demonstruj„cych dzia‡anie najwa¿niejszych mechanizm(cid:243)w (cid:156)rodowiska ASP.NET AJAX. Przedstawione rozwi„zania maj„ bardzo og(cid:243)lny charakter, a zatem mo¿esz szybko dostosowa(cid:230) je do potrzeb w‡asnej aplikacji. Korzystaj„c z tego podrŒcznika, nauczysz siŒ m.in. projektowa(cid:230) w‡asne kontrolki i udostŒpnia(cid:230) je w serwisie Toolkit, poznasz zasady korzystania ze standardowych bibliotek AJAX-a w innych (cid:156)rodowiskach (np. PHP). BŒdziesz umia‡ zbudowa(cid:230) profesjonaln„, dynamiczn„ stronŒ internetow„, bazuj„c„ na platformie ASP.NET AJAX. (cid:149) Struktura i architektura (cid:156)rodowiska ASP.NET AJAX (cid:149) JavaScript (cid:149) Rozszerzenia ASP.NET AJAX (cid:149) Us‡ugi sieciowe (cid:149) Od(cid:156)wie¿anie czŒ(cid:156)ci strony (cid:151) obiekt UpdatePanel (cid:149) Lokalizacja i globalizacja aplikacji (cid:149) ASP.NET Control Toolkit (cid:149) Animacja na stronie WWW (cid:149) Wi„zanie i walidacja danych (cid:149) Zachowania i komponenty (cid:149) Dokumentacja klasy XMLHttpRequest i modelu DOM P‡yæ z nurtem nowoczesno(cid:156)ci (cid:151) tw(cid:243)rz elektryzuj„ce, interaktywne strony WWW! Wydawnictwo Helion ul. Ko(cid:156)ciuszki 1c 44-100 Gliwice tel. 032 230 98 63 e-mail: helion@helion.pl Spis treści Przedmowa ...............................................................................................................................9 I Podstawy ................................................................................................ 17 1. ASP.NET AJAX, Ajax i ASP.NET .................................................................................... 19 19 21 23 29 31 35 37 37 ASP.NET AJAX i Ajax ASP.NET AJAX i ASP.NET Wymagania wstępne i instalacja ASP.NET AJAX Struktura i architektura środowiska ASP.NET AJAX Pierwszy przykład strony ASP.NET AJAX — Witaj użytkowniku Kontrolka ScriptManager Podsumowanie Do dalszego czytania 2. JavaScript .....................................................................................................................39 41 51 54 58 59 59 Język JavaScript Programowanie obiektowe Dostęp do elementów strony Metody modelu DOM Podsumowanie Do dalszego czytania 3. Ajax .............................................................................................................................. 61 61 71 76 79 79 Obiekt XMLHttpRequest Obiekt XMLDocument JSON Podsumowanie Do dalszego czytania 3 II Rozszerzenia ASP.NET AJAX ..................................................................81 4. Wykorzystanie rozszerzeń JavaScript środowiska ASP.NET AJAX ...........................83 83 86 87 98 102 102 Skróty ASP.NET AJAX i funkcje pomocnicze Rozszerzenia istniejących obiektów JavaScript Techniki programowania obiektowego dla języka JavaScript w ASP.NET AJAX Klienckie wersje klas .NET Podsumowanie Do dalszego czytania 5. Usługi sieciowe .......................................................................................................... 103 103 107 110 115 119 129 129 Obsługa błędów Metody strony Przechowywanie informacji o stanie sesji Wymiana złożonych struktur danych między klientem i serwerem Wykorzystanie usług sieciowych z poziomu skryptu JavaScript Podsumowanie Do dalszego czytania 6. Odświeżanie części strony — obiekt UpdatePanel ..................................................131 132 145 146 Przekształcenie fragmentu strony w aktualizowany obszar Podsumowanie Do dalszego czytania 7. Wykorzystanie usługi profili ASP.NET AJAX ............................................................ 147 148 149 154 158 158 Przygotowanie witryny Dostęp do danych profilu Dostęp do danych profilu zdefiniowanych w grupie Podsumowanie Do dalszego czytania 8. Wykorzystanie usługi uwierzytelniania ASP.NET AJAX .......................................... 159 159 162 168 168 Przygotowanie aplikacji Logowanie i wylogowanie Podsumowanie Do dalszego czytania 9. Lokalizacja i globalizacja aplikacji ............................................................................ 169 170 182 186 186 Lokalizacja Globalizacja i internacjonalizacja Podsumowanie Do dalszego czytania 4 | Spis treści III ASP.NET AJAX Control Toolkit .............................................................187 10. Korzystanie z pakietu Control Toolkit ...................................................................... 189 189 192 195 195 Instalacja pakietu Control Toolkit Korzystanie z pakietu kontrolek Podsumowanie Do dalszego czytania 11. Animacja na stronie WWW ....................................................................................... 197 197 204 207 207 Platforma animacji Mechanizm „przeciągnij i upuść” Podsumowanie Do dalszego czytania 12. Automatyczne uzupełnianie wprowadzanych danych, zwalczanie spamu i inne operacje ............................................................................209 Tworzenie harmonijkowych obszarów 209 Zachowanie względnego położenia elementu 211 Wyposażenie kontrolki TextBox w funkcję automatycznego uzupełniania danych 213 Dołączenie kalendarza do pola tekstowego 220 221 Dynamiczne zwijanie pojedynczego panelu 223 Wyświetlanie okna komunikatu 226 Zwalczanie spamu w blogach i na innych forach internetowych Tworzenie zakładek 228 230 Podsumowanie Do dalszego czytania 230 13. Tworzenie i udostępnianie własnych kontrolek ...................................................... 231 231 239 247 248 Tworzenie własnych kontrolek ASP.NET AJAX Dołączenie komponentu do pakietu Control Toolkit Podsumowanie Do dalszego czytania IV ASP.NET AJAX Futures ......................................................................... 249 14. Kontrolki klienckie ..................................................................................................... 251 251 252 267 271 271 Podstawy korzystania z kontrolek klienckich ASP.NET AJAX Korzystanie z kontrolek ASP.NET AJAX Obsługa zdarzeń kontrolek Podsumowanie Do dalszego czytania Spis treści | 5 15. Wiązanie i walidacja danych ....................................................................................273 273 289 303 303 Wiązanie danych Walidacja danych Podsumowanie Do dalszego czytania 16. Zachowania i komponenty ........................................................................................305 305 317 319 319 Wykorzystanie zachowań Wykorzystanie komponentów Podsumowanie Do dalszego czytania 17. Wykorzystanie danych serwerowych ...................................................................... 321 321 336 341 341 Kontrolka ListView Utworzenie własnego źródła danych Podsumowanie Do dalszego czytania 18. Animacje ....................................................................................................................343 343 344 354 354 Zastosowanie animacji Wykorzystanie animacji do uzyskania efektu zanikania Podsumowanie Do dalszego czytania 19. Usprawnianie działania zakładek oraz przycisków „w przód” i „w tył” ...............355 356 Poprawianie kodu Usprawnianie zakładek oraz przycisków „w przód” i „w tył” za pomocą kontrolki UpdateHistory Usprawnianie zakładek oraz przycisków „w przód” i „w tył” za pomocą kontrolek ASP.NET AJAX Futures Podsumowanie Do dalszego czytania 358 362 368 368 20. Rozszerzenie Web Parts ............................................................................................369 Wykorzystanie środowiska ASP.NET AJAX z rozszerzeniem ASP.NET Web Parts 369 374 Podsumowanie Do dalszego czytania 374 6 | Spis treści V Biblioteka Microsoft AJAX ...................................................................375 21. Wykorzystanie ASP.NET AJAX w połączeniu z innymi technologiami sieciowymi ......377 378 382 382 Wykorzystanie rozwiązań ASP.NET AJAX w aplikacji PHP Podsumowanie Do dalszego czytania Dodatki ................................................................................................. 383 A Uruchamianie aplikacji ASP.NET AJAX .....................................................................385 B Dokumentacja klasy XMLHttpRequest .....................................................................397 C Dokumentacja modelu DOM .....................................................................................399 D Dokumentacja środowiska ASP.NET AJAX ...............................................................403 E Dokumentacja kontrolek ScriptManager, UpdatePanel, UpdateProgress i Timer ....407 Skorowidz ..............................................................................................................................411 Spis treści | 7 ROZDZIAŁ 5. Usługi sieciowe Usługa sieciowa została wykorzystana już w pierwszym rozdziale książki w przykładzie aplikacji „Witaj świecie”. Jej zadanie polegało wówczas na przekazywaniu danych między klientem i serwerem. Chcąc jednak skorzystać ze wszystkich możliwości, jakie daje połącze- nie usług sieciowych ze skryptami JavaScript, trzeba się zapoznać z kilkoma bardziej za- awansowanymi sposobami wykorzystywania tego typu rozwiązań. Zaliczają się do nich między innymi: obsługa błędów, stosowanie osadzanych usług sieciowych (metod usług sie- ciowych zawartych w kodzie strony .aspx, zwanych też czasami metodami strony) oraz wy- korzystanie usług sieciowych i skryptów JavaScript bez wsparcia ze strony platformy .NET. W tym rozdziale zostaną przedstawione pewne szczególne rozwiązania środowiska ASP.NET AJAX związane z obsługą usług sieciowych, w tym procedury obsługi błędów oraz prze- chowywanie informacji o stanie sesji. Tematyka rozdziału obejmuje również zasady odwoły- wania się z poziomu skryptów JavaScript do usług sieciowych, które nie zostały przygoto- wane w środowisku ASP.NET. Obsługa błędów W analizowanych wcześniej przykładach zakładaliśmy, że wywołania zdalnych metod zawsze kończą się poprawnie. Nie uwzględnialiśmy możliwości wygenerowania wyjątku. Projektanci serwisów internetowych często pomijają procedury obsługi błędów w przypadku odwołań do usług sieciowych udostępnianych przez zdalne serwery (czyli serwery pracujące w innej domenie). Jedną z przyczyn jest to, że usługi sieciowe można implementować na podstawie różnych technologii, a każda z technologii dysponuje własnym mechanizmem zgłaszania wyjątków, a niektóre z nich w ogóle nie generują wyjątków. W przypadku platformy ASP.NET AJAX i rozwiązań Ajax praca z usługami sieciowymi od- biega nieco od standardowego modelu. Nie można wywoływać bezpośrednio usługi sieciowej, ponieważ zabrania tego system bezpieczeństwa. Domyślnie interpreter JavaScript i obiekt XMLHttpRequest pozwalają jedynie na odwołania z użyciem adresów URI z tej samej dome- ny, z której pochodzi strona. Zatem podczas pracy w środowisku ASP.NET AJAX wywołania usług sieciowych są kierowane do serwera w tej samej domenie. To z kolei oznacza, że sama usługa sieciowa opiera się na technologii .NET (lub WCF — nowym modelu Windows Communication Foundation). Zasady generowania wyjątków są więc znane. 103 Zapewnienie dostępu do wyjątków generowanych przez usługi sieciowe w skryptach Java- Script należy do zadań platformy ASP.NET AJAX. Aby sprawdzić działanie opisywanego mechanizmu, możemy utworzyć usługę matematyczną, która będzie dzieliła dwie liczby. Doprowadzenie do wygenerowania wyjątku nie będzie trudne — wystarczy wymusić dzielenie przez zero, co powinno spowodować wywołanie przez usługę wyjątku DivideByZeroException. Kod usług sieciowej (MathService.asmx) został przedstawiony w przykładzie 5.1. Analizując treść przykładu, warto zwrócić uwagę na atrybuty [ScriptService] i [WebMethod], które muszą być uwzględnione w każdej usłudze sieciowej ASP.NET AJAX. Przykład 5.1. Usługa sieciowa generująca wyjątek MathService.asmx @ WebService Language= C# Class= MathService using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; [WebService(Namespace = http://hauser-wenz.de/AspNetAJAX/ )] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.Web.Script.Services.ScriptService] public class MathService : System.Web.Services.WebService { [WebMethod] public float DivideNumbers(int a, int b) { if (b == 0) { throw new DivideByZeroException( ); } else { return (float)a / b; } } } Przygotujmy stronę, która wywoła usługę sieciową. Potrzebne będą dwa pola edycyjne, w których użytkownik będzie wpisywał liczby do podzielenia oraz dwa obszary na dane wyjściowe — jeden na wynik działania matematycznego, a drugi na ewentualne komunikaty o błędach. Kod musi również obejmować przycisk wywołujący funkcję JavaScript, która na- stępnie wywoła usługę sieciową. nobr input type= text id= a name= a size= 2 / / input type= text id= b name= b size= 2 / = span id= c style= width: 50px; / /nobr br / input type= button value= Podziel liczby onclick= callService(this.form); / br / div id= output style= width: 600px; height: 300px; /div Spośród kontrolek serwerowych na stronie trzeba umieścić komponent ScriptManager wraz z osadzonym w jego treści odniesieniem do wykorzystywanej usługi sieciowej. asp:ScriptManager ID= ScriptManager1 runat= server Services asp:ServiceReference Path= MathService.asmx / /Services /asp:ScriptManager 104 | Rozdział 5. Usługi sieciowe Dzięki takiemu rozwiązaniu wywołania usługi sieciowej mogą być realizowane za pomocą obiektu pośredniczącego o nazwie MathService, który zostanie wygenerowany automatycznie. Podczas wywoływania metody sieciowej konieczne jest zachowanie odpowiedniej kolejności parametrów. Najpierw definiowane są parametry (lub parametr) przekazywane do metody sieciowej, a następnie funkcja zwrotna wykonywana po zakończeniu wywołania metody. Jednak tym razem do metody DivideNumbers() zostanie przekazany jeszcze jeden dodatko- wy parametr. Za funkcją zwrotną, wykonywaną po zakończeniu wywołania, zostanie zdefi- niowana jeszcze jedna funkcja zwrotna. Druga z funkcji zwrotnych będzie wywoływana w przypadku wystąpienia błędów (w tym również w przypadku upłynięcia dopuszczalnego czasu realizacji zadania). function callService(f) { document.getElementById( c ).innerHTML = ; MathService.DivideNumbers( parseInt(f.elements[ a ].value), parseInt(f.elements[ b ].value), callComplete, callError ); } Funkcja obsługi błędów otrzymuje obiekt błędu zawierający pięć metod: get_exceptionType( ) Metoda ta udostępnia informacje o typie wyjątku. get_message( ) Metoda ta zwraca komunikat o błędzie związany z wyjątkiem. get_stackTrace( ) Metoda te zwraca informacje o stosie wywołań funkcji. get_statusCode( ) Metoda ta udostępnia kod statusowy przekazany przez serwer. get_timeOut( ) Metoda ta pozwala na ustalenie, czy został przekroczony maksymalny czas realizacji za- dania. Informacje na temat błędu są wyświetlane w obszarze elementu div , który został utworzony specjalnie w tym celu. function callError(result) { document.getElementById( output ).innerHTML = b + result.get_exceptionType( ) + /b : + result.get_message( ) + br / + result.get_stackTrace( ); } Przygotowanie pozostałej części kodu nie powinno nastręczać większych trudności. Gdy wywołanie usługi sieciowej zakończy się pomyślnie, wynik powinien zostać wyświetlony w obszarze elementu span . Pełna treść strony została przedstawiona w przykładzie 5.2. Obsługa błędów | 105 Przykład 5.2. Strona wyświetlająca wyjątek wygenerowany przez usługę MathService.asmx Error.aspx @ Page Language= C# !DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd html xmlns= http://www.w3.org/1999/xhtml head id= Head1 runat= server title ASP.NET AJAX /title script language= Javascript type= text/javascript function callService(f) { document.getElementById( c ).innerHTML = ; document.getElementById( output ).innerHTML = ; MathService.DivideNumbers( parseInt(f.elements[ a ].value), parseInt(f.elements[ b ].value), callComplete, callError); } function callComplete(result) { document.getElementById( c ).innerHTML = result; } function callError(result) { document.getElementById( output ).innerHTML = b + result.get_exceptionType() + /b : + result.get_message() + br / + result.get_stackTrace(); } /script /head body form id= form1 runat= server asp:ScriptManager ID= ScriptManager1 runat= server Services asp:ServiceReference Path= MathService.asmx / /Services /asp:ScriptManager div nobr input type= text id= a name= a size= 2 / : input type= text id= b name= b size= 2 / = span id= c style= width: 50px; /span /nobr br / input type= button value= Podziel liczby onclick= callService(this.form); / br / div id= output style= width: 600px; height: 300px; /div /div /form /body /html 106 | Rozdział 5. Usługi sieciowe Podzielenie liczby 5 przez 6 daje spodziewany wynik 0.8333333. Jednak próba podzielenia liczby 5 przez 0 powoduje wygenerowanie przez usługę sieciową wyjątku, a w konsekwencji wyświetlenie komunikatu o błędzie wraz ze stosem wywołań funkcji (wygląd strony został pokazany na rysunku 5.1). Rysunek 5.1. Wyświetlenie informacji na temat wyjątku Informacja na temat (nie)wyświetlania komunikatów o błędach Wyświetlanie komunikatów o błędach w aplikacji klienckiej jest doskonałym rozwiązaniem na czas uruchamiania aplikacji. Stanowi jednak bardzo duże zagrożenie w środowisku użyt- kowym. Komunikaty o błędach mogą bowiem zawierać tajne dane, takie jak parametry cią- gów połączenia. Nawet jeśli nie są bezpośrednio wyświetlane w oknie przeglądarki środo- wisko ASP.NET AJAX może je przekazywać do aplikacji klienckiej. Aby temu zapobiec, należy wykonać dwie czynności. Po pierwsze trzeba sprawdzić, czy do przeglądarki nie są dostarczane szczegółowe opisy błędu (obejmujące dane na temat stosu wywołań funkcji). Po drugie generując wyjątek po stronie serwera należy uwzględnić w komunikacie możliwie najmniejszą ilość szczegółowych informacji. Metody strony Prawdopodobnie większość programistów zgodzi się z twierdzeniem, że umieszczanie wszystkich metod sieciowych aplikacji w oddzielnym pliku jest dość uciążliwe. Pod względem struktury aplikacji taki sposób zarządzania plikami wydaje się właściwy. Jednak w przypad- ku nieskomplikowanych skryptów i aplikacji (takich jak większość opisywanych w książce) dodatkowy plik .asmx niepotrzebnie rozbudowuje projekt. Metody strony | 107 Przy niewiele większym narzucie kodowym (lub nawet zmniejszeniu ilości kodu w pewnych okolicznościach) istnieje możliwość zamieszczenia całego skryptu w jednym miejscu — w głów- nym pliku .aspx (lub w związanym z nim pliku klasy). Procedura przygotowania opisywanego rozwiązania składa się z dwóch etapów. Pierwszy sprowadza się do zaimportowania do pliku strony przestrzeni nazw usług sieciowych: @ Import Namespace= System.Web.Services Drugi etap polega na dołączeniu treści metody sieciowej do kodu strony. Metoda usługi sie- ciowej (a dokładnie metoda działająca jak metoda sieciowa) musi zostać oznaczona za pomocą atrybutu [WebMethod] — podobnie jak w pliku .asmx. Obsługa osadzanych metod usług sie- ciowych w środowisku ASP.NET AJAX ma również pewne ograniczenia. Oto one: • Metoda musi być oznaczona za pomocą atrybutu ScriptMethod, opisanego w przestrzeni nazw System.Web.Script.Services. • Metoda musi być zadeklarowana jako publiczna (public). • Metoda musi być zadeklarowana jako statyczna (static). Przykład metody spełniającej wszystkie wymienione wymagania został przedstawiony poniżej: script runat= server [WebMethod] [System.Web.Script.Services.ScriptMethod] public static float DivideNumbers(int a, int b) { if (b == 0) { throw new DivideByZeroException( ); } else { return (float)a / b; } } /script Środowisko ASP.NET AJAX automatycznie wyszukuje wszystkie opisane w ten sposób metody i dołącza je do klasy klienckiej PageMethods. Zatem aby wywołać metodę strony, wystarczy posłużyć się zapisem PageMethods.DivideNumbers() zgodnie z poniższym przykładem. function callService(f) { document.getElementById( c ).innerHTML = ; PageMethods.DivideNumbers( parseInt(f.elements[ a ].value), parseInt(f.elements[ b ].value), callComplete, callError); } Ostatnia czynność projektowa pola na włączeniu wywołań do osadzonych metod usług sie- ciowych. W terminologii ASP.NET AJAX metody te są nazywane „metodami strony” (ang. page methods). Ich włączenie wymaga przypisania wartości true do właściwości EnablePage- Methods kontrolki ScriptManager: asp:ScriptManager ID= a1 runat= server EnablePageMethods= true / 108 | Rozdział 5. Usługi sieciowe W przykładzie 5.3 został zamieszczony pełen kod strony ASP.NET, w której znajduje się za- równo treść samej strony, jak i metoda usługi sieciowej. Przykład 5.3. Kod usługi sieciowej i strony ASP.NET AJAX zapisane w jednym pliku Inline.aspx @ Page Language= C# @ Import Namespace= System.Web.Services !DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd script runat= server [WebMethod] [System.Web.Script.Services.ScriptMethod] public static float DivideNumbers(int a, int b) { if (b == 0) { throw new DivideByZeroException(); } else { return (float)a / b; } } /script html xmlns= http://www.w3.org/1999/xhtml head id= Head1 runat= server title ASP.NET AJAX /title script language= Javascript type= text/javascript function callService(f) { document.getElementById( c ).innerHTML = ; PageMethods.DivideNumbers( parseInt(f.elements[ a ].value), parseInt(f.elements[ b ].value), callComplete, callError); } function callComplete(result) { document.getElementById( c ).innerHTML = result; } function callError(result) { document.getElementById( output ).innerHTML = b + result.get_exceptionType() + /b : + result.get_message() + br / + result.get_stackTrace(); } /script /head body form id= form1 runat= server asp:ScriptManager ID= ScriptManager1 runat= server Metody strony | 109 EnablePageMethods= true /asp:ScriptManager div nobr input type= text id= a name= a size= 2 / : input type= text id= b name= b size= 2 / = span id= c style= width: 50px; /span /nobr br / input type= button value= Podziel liczby onclick= callService(this.form); / br / div id= output style= width: 600px; height: 300px; /div /div /form /body /html Wynik wyświetlany po załadowaniu strony, wprowadzeniu dwóch wartości i kliknięciu przycisku Podziel liczby został pokazany na rysunku 5.2. Rysunek 5.2. Jeden plik, jedna usługa sieciowa, jedna operacja dzielenia Przechowywanie informacji o stanie sesji Usługi sieciowe zyskały sobie miano doskonałej technologii, która nie ma nic wspólnego z aplikacjami sieciowymi. Jednak od kiedy zostały zintegrowane z platformą .NET i witrynami ASP.NET, programiści zyskali możliwość projektowania rozwiązań, które znacznie wykraczają poza funkcje samych usług sieciowych. Usługi sieciowe platformy .NET pozwalają między innymi na przetwarzanie informacji o stanie sesji. Dane zapisane w sesji są (dzięki środowisku ASP.NET AJAX) udostępniane nawet aplikacjom bazującym na technologii Ajax. Na przykład środowisko ASP.NET AJAX gwarantuje różnym aplikacjom Ajax (uruchomionym na jednym serwerze) dostęp do danych tego samego użytkownika. 110 | Rozdział 5. Usługi sieciowe Zaimplementowanie opisywanego mechanizmu jest łatwiejsze niż jego omówienie. Za dostęp do danych sesji odpowiada właściwość EnableSession atrybutu [WebMethod]. Jej przezna- czenie jest takie samo, jak w przypadku metody sieciowej aplikacji .NET. [WebMethod(EnableSession=true)] Po uwzględnieniu właściwości EnableSession można bezpośrednio odwoływać się do obiektu Session platformy ASP.NET i zapisać lub odczytywać dane. Ponieważ metody sie- ciowe muszą mieć charakter metod statycznych, konieczne jest zastosowanie odwołania HttpContext.Current.Session, a nie po prostu Session. Pierwsze z odwołań odnosi się jedynie do obiektów bieżącej instancji klasy Page. W następnym fragmencie skryptu zostały zaprezentowane dwie funkcje. Pierwsza z nich za- pisuje bieżącą wartość czasu w sesji. Natomiast druga oblicza różnicę między czasem bieżą- cym a znacznikiem czasu zapisanym w sesji. Jeśli w sesji nie została zapisana żadna wartość, funkcja zwraca wartość -1. [WebMethod(EnableSession = true)] [System.Web.Script.Services.ScriptMethod] public static bool SaveTime( ) { HttpContext.Current.Session[ PageLoaded ] = DateTime.Now; return true; } [WebMethod(EnableSession = true)] [System.Web.Script.Services.ScriptMethod] public static double CalculateDifference( ) { if (HttpContext.Current.Session[ PageLoaded ] == null) { return -1; } else { DateTime then = (DateTime)HttpContext.Current.Session[ PageLoaded ]; TimeSpan diff = DateTime.Now.Subtract(then); return diff.TotalSeconds; } } Powróćmy na chwilę do aplikacji dzielenia dwóch liczb. Do strony zwierającej kod aplikacji zostanie dodana metoda SaveTime(), która zapisze wartość czasu, właściwą dla chwili ła- dowania skryptu. Z kolei w momencie obliczania wyniku dzielenia wyznaczona zostanie różnica między czasem bieżącym a zarejestrowanym wcześniej. W ten sposób będzie można ustalić, ile czasu minęło od pobrania strony do obliczenia wyniku działania (które oczywiście można również wykonać w samym języku JavaScript; celem przykładu jest jednak zademon- strowanie innego rozwiązania). Kolejny fragment kodu JavaScript odpowiada za wywołanie metody sieciowej (SaveTime()), która zarejestruje czas w chwili pobrania strony. Ponieważ w operacji tej nie jest zwracana żadna wartość wynikowa, funkcja zwrotna może być funkcją pustą function pageLoad( ){ PageMethods.SaveTime(doNothing, doNothing); } function doNothing(result) { //nic :-) } Przechowywanie informacji o stanie sesji | 111 Zgodnie z wcześniejszymi założeniami konieczne jest również zdefiniowanie metody (call- Service()), która wywoła metodę CalculateDifference() usługi sieciowej. Zamieszczony poniżej kod uwzględnia dwa wywołania metod sieciowych. Pierwsze odpowiada za oblicze- nie różnicy czasu między pobraniem strony a kliknięciem przycisku. Drugie natomiast po- woduje wykonanie samego działania matematycznego. function callService(f) { document.getElementById( c ).innerHTML = ; PageMethods.CalculateDifference( showDifference, callError); PageMethods.DivideNumbers( parseInt(f.elements[ a ].value), parseInt(f.elements[ b ].value), callComplete, callError); } Potrzebny będzie jeszcze pewien kod HTML, który pozwoli na wyświetlenie informacji o czasie. Wykorzystamy do tego celu kontener div . Należy pamiętać, że wynik o wartości -1 oznacza, że w sesji nie został zarejestrowany znacznik czasu i w związku z tym nie można obliczyć różnicy czasowej. function showDifference(result) { if (result != -1) { document.getElementById( output ).innerHTML = Formularz był wyświetlany przez + result + sekund ; } } Kompletny kod strony (treść HTML i skrypt niezbędny do zaimplementowania algorytmu) został przedstawiony w przykładzie 5.4. Wszystkie zmiany w treści zostały odpowiednio wyróżnione. Aby aplikacja działała poprawnie, trzeba pamiętać o dodaniu atrybutu Enable- PageMethods= true do kodu kontrolki ScriptManager. Brak atrybutu uniemożliwia wy- wołanie metody strony. Przykład 5.4. Wykorzystanie sesji w aplikacji ASP.NET AJAX i ASP.NET WebServiceSession.aspx @ Page Language= C# @ Import Namespace= System.Web.Services !DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd script runat= server [WebMethod(EnableSession = true)] [System.Web.Script.Services.ScriptMethod] public static bool SaveTime() { HttpContext.Current.Session[ PageLoaded ] = DateTime.Now; return true; } [WebMethod(EnableSession = true)] [System.Web.Script.Services.ScriptMethod] public static double CalculateDifference() { 112 | Rozdział 5. Usługi sieciowe if (HttpContext.Current.Session[ PageLoaded ] == null) { return -1; } else { DateTime then = (DateTime)HttpContext.Current.Session[ PageLoaded ]; TimeSpan diff = DateTime.Now.Subtract(then); return diff.TotalSeconds; } } [WebMethod] [System.Web.Script.Services.ScriptMethod] public float DivideNumbers(int a, int b) { if (b == 0) { throw new DivideByZeroException(); } else { return (float)a / b; } } /script html xmlns= http://www.w3.org/1999/xhtml head id= Head1 runat= server title ASP.NET AJAX /title script language= Javascript type= text/javascript function pageLoad() { PageMethods.SaveTime(doNothing, doNothing, doNothing); } function doNothing(result) { //nic :-) } function callService(f) { document.getElementById( c ).innerHTML = ; PageMethods.CalculateDifference( showDifference, callError); PageMethods.DivideNumbers( parseInt(f.elements[ a ].value), parseInt(f.elements[ b ].value), callComplete, callError); } function showDifference(result) { if (result != -1) { document.getElementById( output ).innerHTML = Formularz był wyświetlany przez + result + sekund ; } } function callComplete(result) { document.getElementById( c ).innerHTML = result; } function callError(result) { if (result == null) { window.alert( Błąd! ); } else { Przechowywanie informacji o stanie sesji | 113 document.getElementById( output ).innerHTML = b + result.get_exceptionType() + /b : + result.get_message() + br / + result.get_stackTrace(); } } /script /head body form id= form1 runat= server asp:ScriptManager ID= ScriptManager1 runat= server EnablePageMethods= true /asp:ScriptManager div nobr input type= text id= a name= a size= 2 / : input type= text id= b name= b size= 2 / = span id= c style= width: 50px; /span /nobr br / input type= button value= Podziel liczby onclick= callService(this.form); / br / div id= output style= width: 600px; height: 300px; /div /div /form /body /html Podczas wykonywania metody DivideNumbers() można zauważyć nieco inne działanie przeglądarki niż w poprzednich zadaniach. Po pierwsze, serwer dostarcza plik cookie zwią- zany z sesją (o ile w pliku Web.config nie została włączona opcja zarządzania sesją bez użycia plików cookie). Jeżeli w przeglądarce została włączona opcja pytania o zezwolenie na przyję- cie pliku cookie, na ekranie powinno się wyświetlić okno, zbliżone do przedstawionego na rysunku 5.3. Druga różnica wiąże się z zachowaniem danych sesji pomiędzy odwołaniami do usługi sieciowej (rysunek 5.4). Rysunek 5.3. Środowisko ASP.NET przesyła plik cookie związany z sesją dla danej strony 114 | Rozdział 5. Usługi sieciowe Rysunek 5.4. Wykorzystanie sesji do przechowywania wartości czasu (niezbędnej do obliczenia przerwy między pobraniem strony i wykonaniem działania) Wymiana złożonych struktur danych między klientem i serwerem We wcześniejszych przykładach analizowaliśmy jedynie wymianę między serwerem i klientem ciągów tekstowych i wartości typów prostych (liczb, wartości logicznych). Nic jednak nie stoi na przeszkodzie, aby objąć tym mechanizmem również operację dostarczania bardziej złożo- nych struktur danych. Co prawda język JavaScript nie może konkurować z bogatszymi pod względem liczby typów językami platformy .NET, ale format JSON (opisany w rozdziale 3.) zapewnia podstawową obsługę tablic i obiektów. Środowisko ASP.NET AJAX jest standardowo wyposażone w mechanizmy serializacji i dese- rializacji danych JSON. Jeśli więc uwzględnimy je w kodzie usługi sieciowej zaprezentowanej w przykładach 5.1 i 5.2, będziemy mogli udostępnić nową metodę, która za jednym razem zwróci dwie informacje — wynik dzielenia liczb oraz wartość znacznika czasu serwerowego. Aby wdrożyć opisane rozwiązanie, utworzymy w pliku MathService.asmx nową klasę, która będzie opisywała zwracany obiekt. public class DivisionData { public float result; public string calculationTime; } Powołanie i zwrócenie obiektu będzie należało do metody przedstawionej poniżej. [WebMethod] public DivisionData ExtendedDivideNumbers(int a, int b) { if (b == 0) { throw new DivideByZeroException( ); } else { float res = (float)a / b; string stamp = DateTime.Now.ToLongTimeString( ); DivisionData d = new DivisionData( ); d.result = res; Wymiana złożonych struktur danych między klientem i serwerem | 115 d.calculationTime = stamp; return d; } } Aby zwracany obiekt był dostępny dla kodu JavaScript, aplikacja ASP.NET AJAX musi go przekształcić (w procesie serializacji) w odpowiedni ciąg JSON. Za użycie właściwej definicji obiektu odpowiada atrybut GenerateScriptType (zdefiniowany w przestrzeni nazw System.Web.Script.Services [w której zostały zapisane również atrybuty Script- Service i ScriptMethod]): [System.Web.Script.Services.GenerateScriptType(typeof(DivisionData))] Po stronie serwera nie trzeba wprowadzać więcej zmian. Zaktualizowana treść pliku Math- Service.asmx została zamieszczona w przykładzie 5.5. Przykład 5.5. Zaktualizowany plik usługi MathService MathService.asmx @ WebService Language= C# Class= MathService using System; using System.Web; using System.Web.Services; using System.Web.Services.Protocols; public class DivisionData { public float result; public string calculationTime; } [WebService(Namespace = http://hauser-wenz.de/AspNetAJAX/ )] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.Web.Script.Services.ScriptService] [System.Web.Script.Services.GenerateScriptType(typeof(DivisionData))] public class MathService : System.Web.Services.WebService { [WebMethod] public float DivideNumbers(int a, int b) { if (b == 0) { throw new DivideByZeroException(); } else { return (float)a / b; } } [WebMethod] public DivisionData ExtendedDivideNumbers(int a, int b) { if (b == 0) { throw new DivideByZeroException(); } else 116 | Rozdział 5. Usługi sieciowe { float res = (float)a / b; string stamp = DateTime.Now.ToLongTimeString(); DivisionData d = new DivisionData(); d.result = res; d.calculationTime = stamp; return d; } } } Po stronie klienta deserializacja obiektu DivisionData jest realizowana w sposób automa- tyczny. Obiekt będący wynikiem wywołania usługi sieciowej ma te same właściwości (result i calculationTime), jakie zostały zdefiniowane w obiekcie DivisionData. Instrukcje Java- Script potrzebne do wywołania zmodyfikowanej usługi sieciowej zostały przedstawione w przykładzie 5.6. Przykład 5.6. Kod strony pobierającej z metody sieciowej bardziej rozbudowane obiekty Complex.aspx @ Page Language= C# !DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd html xmlns= http://www.w3.org/1999/xhtml head id= Head1 runat= server title ASP.NET AJAX /title script language= Javascript type= text/javascript function callService(f) { document.getElementById( c ).innerHTML = ; document.getElementById( output ).innerHTML = ; MathService.ExtendedDivideNumbers( parseInt(f.elements[ a ].value), parseInt(f.elements[ b ].value), callComplete, callError); } function callComplete(result) { document.getElementById( c ).innerHTML = result.result + (obliczono o godzinie + result.calculationTime + ) ; } function callError(result) { document.getElementById( output ).innerHTML = b + result.get_exceptionType() + /b : + result.get_message() + br / + result.get_stackTrace(); } /script /head Wymiana złożonych struktur danych między klientem i serwerem | 117 body form id= form1 runat= server asp:ScriptManager ID= ScriptManager1 runat= server Services asp:ServiceReference Path= MathService.asmx / /Services /asp:ScriptManager div nobr input type= text id= a name= a size= 2 / : input type= text id= b name= b size= 2 / = span id= c style= width: 50px; /span /nobr br / input type= button value= Podziel liczby onclick= callService(this.form); / br / div id= output style= width: 600px; height: 300px; /div /div /form /body /html Sposób prezentacji wyniku dzielenia i czasu wygenerowania odpowiedzi został pokazany na rysunku 5.5. Rysunek 5.5. Wyświetlenie informacji dostarczonych przez serwer Przechwytując ruch HTTP generowany przez skrypt, możemy sprawdzić, w jaki sposób zło- żona struktura danych została przekształcona w blok danych JSON (rysunek 5.6). Opisane do tej pory funkcje środowiska ASP.NET AJAX związane z usługami sieciowymi byłby niezwykle trudne do zaimplementowania za pomocą samego języka JavaScript. Plat- forma ASP.NET AJAX doskonale integruje się z usługami sieciowymi .NET i stanowi bardzo użyteczny pomost między technologią JavaScript (po stronie klienckiej) i technologią ASP.NET (po stronie serwera). 118 | Rozdział 5. Usługi sieciowe Rysunek 5.6. Złożona struktura danych po serializacji do formatu JSON Wykorzystanie usług sieciowych z poziomu skryptu JavaScript Zapewniane przez środowisko ASP.NET AJAX mechanizmy odwołań do usług sieciowych są niezwykle użyteczne, ponieważ automatycznie realizują wszystkie związane z tą operacją zadania. Zdarzają się jednak sytuacje, w których nie można ich zastosować. Przykładem może być konieczność odwołania się do usługi sieciowej (w tej samej domenie), która nie została napisana dla platformy .NET, lecz opiera się na innych rozwiązaniach serwerowych, takich jak PHP lub Java. Innym powodem bywa również polityka firmy dotycząca stosowania mo- dułów zewnętrznych producentów lub brak akceptacji dla określonej umowy licencyjnej. Ponieważ zakres tematyczny książki wykracza poza samo korzystanie ze środowiska ASP.NET AJAX i obejmuje wszystkie zagadnienia związane z tworzeniem aplikacji Ajax na platformie ASP.NET, omówione zostaną tutaj także zasady wywoływania zdalnych usług sieciowych z poziomu skryptu JavaScript. Zanim przystąpimy do szczegółowego analizowania stosownych mechanizmów, warto sobie przypomnieć, że model zabezpieczeń języka JavaScript zabrania wykonywania skryptów po- chodzących z różnych domen. Oznacza to, że nie można odwołać się do zdalnych witryn za pomocą instrukcji JavaScript (korzystających z obiektu XMLHttpRequest). Wykorzystanie usług sieciowych z poziomu skryptu JavaScript | 119 Istnieją dwie metody programowego wywoływania usług sieciowych w języku JavaScript. Pierwsza z nich polega na zastosowaniu obiektu XMLHttpRequest. Natomiast w drugiej za- kłada się przygotowanie własnego żądania HTTP SOAP i samodzielną interpretację danych zwracanych przez serwer. Druga metoda jest dość skomplikowana i bardzo podatna na błędy. Znacznie lepszym rozwiązaniem jest wykorzystanie mechanizmów wbudowanych w prze- glądarką oraz oficjalnych dodatków do przeglądarki, Niestety, dwie najpowszechniej stosowane aplikacje — Internet Explorer i Mozilla (czyli Firefox, Epiphany, Camino itd.) — mają zaimplementowane dwie zupełnie różne procedury wywo- ływania usług sieciowych. W rezultacie programista musi powielać kod zapewniający obsługę każdej z przeglądarek. W końcowej części podrozdziału zostało jednak przedstawione roz- wiązanie, które pozwala na połączenie obydwu modeli, a tym samym na opracowanie skryptu (bardziej lub mniej) niezależnego od rodzaju oprogramowania klienckiego. Usługi sieciowe w przeglądarkach Internet Explorer Kilka lat temu firma Microsoft rozpoczęła prace na kodem skryptowym, który umożliwiałby wywoływanie usług sieciowych z poziomu samej przeglądarki. Zgodnie z założeniami kod taki powinien powoływać obiekt XMLHttpRequest, definiować niezbędne nagłówki HTTP dla żądania SOAP, przygotowywać treść samego żądania, następnie oczekiwać na odpowiedź SOAP i przekształcać wynik do formatu właściwego do dalszego przetwarzania w instruk- cjach JavaScript. Ponadto powinien umożliwiać interpretowanie informacji generowanych w języku opisu usług sieciowych (WSDL — ang. Web Service Description Language) oraz gene- rowanie lokalnego obiektu pośredniczącego. Idea nie jest skomplikowana, ale implementacja tak. Ostateczna wersja mechanizmu (wersja 1.0.1.1120) składa się z niemal 2300 wierszy kodu. Niestety, w 2002 roku firma Microsoft przerwała prace nad komponentem komunikacji z usługami sieciowymi. Szkoda, gdyż do dzisiaj jest on wykorzystywany i działa poprawnie. Na szczęście jest jeszcze dostępny w ar- chiwach MSDN pod adresem http://msdn.microsoft.com/archive/en-us/samples/internet/behaviors/ library/webservice/default.asp. Aby z niego skorzystać, trzeba pobrać plik webservice.htc i zapisać w katalogu, w którym prze- chowywane są skrypty przykładów. Rozszerzenie .htc oznacza kontrolkę HTML (HTML control), zwaną też funkcją (ang. behavior) przeglądarki Internet Explorer. Do załadowania pliku służy niestandardowa instrukcja stylu CSS, obsługiwana jedynie w aplikacjach Internet Explorer. div id= WebService style= behavior:url(webservice.htc); /div Nazwa podana jako wartość atrybutu id może być wykorzystana w skrypcie w JavaScript zarówno do odwołania do samej kontrolki HTML, jak i do odwołania do usługi sieciowej z nią związanej. Powiązanie kontrolki z usługą wymaga zdefiniowania odsyłacza do opisu WSDL danej usługi sieciowej. Wykorzystuje się do tego celu metodę useService() zapisaną w pliku .htc. Konieczne jest również określenie niepowtarzalnego identyfikatora, który umożliwi późniejsze odwoły- wanie się do danej usługi sieciowej. WebService.useService( MathService.asmx?WSDL , MathService ); 120 | Rozdział 5. Usługi sieciowe Po tych operacjach można wywołać usługę. Kolejność parametrów przekazywanych do me- tody callService() — odpowiadającej za wywołanie usługi sieciowej — różni się od stoso- wanej w obiektach pośredniczących ASP.NET AJAX. Oto lista tych parametrów: • referencja do metody zwrotnej, • nazwa wywoływanej metody sieciowej, • parametry przekazywane do usługi sieciowej. Rozwiązanie to nie zapewnia obsługi błędów (w przeciwieństwie do mechanizmów ASP.NET AJAX, które dostarczają wyjątki do skryptu klienckiego). W przypadku odwołania do usługi MathService podzielenie dwóch liczb wymagałoby wy- konania następującej instrukcji: WebService.MathService.callService( callComplete, DivideNumbers , 6, 7); Funkcja zwrotna otrzymuje wówczas obiekt, którego atrybut value zawiera wynik zwrócony przez usługę sieciową. function callComplete(result) { document.getElementsById( c ).innerHTML = result.value; } Pełny kod aplikacji został zamieszczony w przykładzie 5.7. Przykład 5.7. Wywołanie usługi sieciowej w przeglądarce Internet Explorer MathServiceInternetExplorer.htm !DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd html xmlns= http://www.w3.org/1999/xhtml head title ASP.NET AJAX /title script language= Javascript type= text/javascript function callService(f) { document.getElementById( c ).innerHTML = ; WebService.useService( MathService.asmx?WSDL , MathService ); WebService.MathService.callService( callComplete, DivideNumbers , f.elements[ a ].value, f.elements[ b ].value); } function callComplete(result) { document.getElementById( c ).innerHTML = result.value; } /script /head body div id= WebService style= behavior:url(webservice.htc); /div form method= post onsubmit= return false; div nobr Wykorzystanie usług sieciowych z poziomu skryptu JavaScript | 121 input type= text id= a name= a size= 2 / : input type= text id= b name= b size= 2 / = span id= c style= width: 50px; /span /nobr br / input type= button value= Podziel liczby onclick= callService(this.form); / /div /form /body /html Jeśli kontrolka HTML usługi sieciowej nie zostanie zdefiniowana na początku sekcji body , przeglądarka może wygenerować niepokojące komunikaty o błędach, włącznie z informacją o tym, że obiekt WebService nie został zdefiniowany (mimo prawidłowego działania instrukcji window.alert(WebService)). Usługi sieciowe w przeglądarkach Mozilla Obsługa usług sieciowych została zaimplementowana również w wydawanych ostatnio wer- sjach przeglądarek Mozilla. Ma ona charakter wbudowanego rozszerzenia. Niestety, kompo- nent odpowiedzialny za komunikację z usługami sieciowymi najwyraźniej nie zyskał szcze- gólnego zainteresowania u osób skupionych wokół projektu Mozilla, choć trzeba przyznać, że poprawnie wykonuje swoje zadanie. W rezultacie nie towarzyszy mu żadna dokumentacja, a informacje na temat jego użycia są często sprzeczne. Rozwiązanie prezentowane w dalszej części punktu pozwala na realizację zadnia, ale wymaga dodania sporej ilości kodu. Za komunikację z usługami sieciowymi odpowiada klasa SOAPCall. Ponieważ opiera się ona na standardzie SOAP 1.1, programista musi zdefiniować nagłówek SOAPAction (dostępny w formie właściwości klasy SOAPClass) oraz adres URL pliku usługi sieciowej. Oto instrukcje charakterystyczne dla omawianego przykładu: var soapcall = new SOAPCall( ); soapcall.actionURI = http://hauser-wenz.de/AspNetAJAX/DivideNumbers ; soapcall.transportURI = http://localhost:1234/AJAXEnabledWebSite1/MathServiceDocEnc.asmx ; Wartość właściwości transportURI musi bezwzględnie odpowiadać adresowi URL. Trzeba więc pamiętać o dostosowaniu ciągu URI (szczególnie numeru portu, jeśli do uruchamiania aplikacji jest wykorzystywany serwer testowy środowiska Visual Studio lub Visual Web Developer) do ustawień lokalnego systemu. Wszystkie parametry przekazywane do usługi są zmiennymi typu SOAPParameter. W kon- struktorze klasy parametru należy wskazać wartość parametru, a następnie jego nazwę. var p1 = new SOAPParameter(6, a ); var p2 = new SOAPParameter(7, b ); Bardzo ważne jest wykonanie następnej czynności. Jej ewentualne pominięcie spowoduje, że żądanie SOAP zostanie przesłane do serwera (odebrana zostanie również wartość wyniku), ale nie będą do niego dołączone parametry. W przypadku dzielenia liczb oznaczałoby to nie- zamierzone wygenerowanie wyjątku dzielenia przez zero (ang. divie by zero). 122 | Rozdział 5. Usługi sieciowe Zadanie polega na osobistym ustaleniu właściwego kodowania dla wartości liczbowych. W tym celu należy załadować odpowiednią przestrzeń nazw, która obejmuje typ SOAP integer. Następnie trzeba określić wartość właściwości schemaType wszystkich parametrów, które powinny być przekazane do usługi sieciowej, przypisując im wygenerowane typy danych. Kod realizujący opisane zadania został zamieszczony poniżej. var senc = new SOAPEncoding( ); assenc = senc.getAssociatedEncoding( http://schemas.xmlsoap.org/soap/encoding/ , false); var scoll = assenc.schemaCollection; var stype = scoll.getType( integer , http://www.w3.org/2001/XMLSchema ); p1.schemaType = stype; p2.schemaType = stype; Kolejna czynność polega na przygotowaniu wywołania usługi sieciowej. Służy do tego metoda encode(), wymagająca przekazania do niej kilku parametrów, zgodnie z poniższym przykładem. soapcall.encode( 0, //wartość domyślna dla protokołu SOAP 1.1 DivideNumbers , //nazwa metody sieciowej http://hauser-wenz.de/AspNetAJAX/ , //przestrzeń nazw 0, //liczba dodatkowych nagłówków new Array( ), //dodatkowe nagłówki 2, //liczba parametrów new Array(p1, p2) //parametry ); W końcu można wywołać usługę sieciową (w sposób asynchroniczny), wykonując metodę asyncInvoke(). Parametrem metody jest referencja funkcji zwrotnej. soapcall.asyncInvoke(callComplete); Funkcja zwrotna otrzymuje trzy parametry: • dokument XML będący wynikiem wywołania usługi sieciowej, • obiekt SOAPCall (gdyby konieczne było przeanalizowanie nagłówków SOAP), • kod statusowy HTTP dla wywołania. Ostatni etap procedury sprowadza się do wyodrębnienia danych wynikowych z treści do- starczonego dokumentu XML. Przyjrzyjmy się zatem odpowiedzi XML zwracanej po odwo- łaniu się do usługi MathService — dane te można pozyskać za pomocą programu Fiddler (dla systemu Windows) (http://www.fiddlertool.com/fiddler) lub rozszerzenia przeglądarki Mozilla Live HTTP Headers (http://livehttpheaders.mozdev.org/): ?xml version= 1.0 encoding= utf-8 ? soap:Envelope xmlns:xsi= http://www.w3.org/2001/XMLSchema-instance xmlns:xsd= http://www.w3.org/2001/XMLSchema xmlns:soap= http://schemas.xmlsoap .org/soap/envelope/ soap:Body DivideNumbersResponse xmlns= http://hauser-wenz.de/AspNetAJAX/ DivideNumbersResult 0.857142866 /DivideNumbersResult /DivideNumbersResponse /soap:Body /soap:Envelope Wykorzystanie usług sieciowych z poziomu skryptu JavaScript | 123 Więcej informacji na temat sposobu analizowania żądań HTTP (wysyłanych przez aplikacje Ajax) oraz debugowania aplikacji Ajax znajduje się w dodatku A. Analizując dane w formacie XML, nietrudno zauważyć, że wyodrębnienie wartości 0.857142866 wymaga przeprowadzenia następujących operacji: • odwołania się do właściwości body, która zapewni dostęp do elementu soap:Body ; • odwołania się do właściwości firstChild, która zapewni dostęp do elementu Divide- NumbersResponse ; • ponownego wykorzystania właściwości firstChild do pobrania elementu DivideNum- bersResult ; • wykorzystania po raz trzeci właściwości firstChild, aby uzyskać dostęp do węzła tek- stowego w elemencie DivideNumbersResult ; • wykorzystania właściwości data do pobrania ciągu zapisanego w węźle tekstowym. Treść skryptu JavaScript niezbędnego do wyodrębnienia wyniku z dokumentu dostarczonego przez usługę sieciową została zamieszczona poniżej. function callComplete(result, soapcall, status) { document.getElementById( c ).innerHTML = result.body.firstChild.firstChild.firstChild.data; } Łącząc wszystkie opisane fragmenty skryptów, uzyskujemy kod przedstawiony w przykła- dzie 5.8. Trzeba jednak pamiętać, że aplikacja będzie działała zgodnie z oczekiwaniami tylko wtedy, gdy system będzie miał dostęp do internetu — przeglądarki Mozilla muszą mieć do- stęp do informacji na temat schematów SOAP. Przykład 5.8. Wywołanie usługi sieciowej w przeglądarce Mozilla MathServiceMozilla.htm !DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd html xmlns= http://www.w3.org/1999/xhtml head title ASP.NET AJAX /title script language= Javascript type= text/javascript function callService(f) { document.getElementById( c ).innerHTML = ; var soapcall = new SOAPCall( ); soapcall.actionURI = http://hauser-wenz.de/AspNetAJAX/DivideNumbers ; soapcall.transportURI= http://localhost:1041/AJAXEnabledWebSite1/MathService.asmx ; var p1 = new SOAPParameter(parseInt(f.elements[ a ].value), a ); var p2 = new SOAPParameter(parseInt(f.elements[ b ].value), b ); var senc = new SOAPEncoding( ); assenc = senc.getAssociatedEncoding( http://schemas.xmlsoap.org/soap/encoding/ , false); var scoll = assenc.schemaCollection; var stype = scoll.getType( integer , 124 | Rozdział 5. Usługi sieciowe http://www.w3.org/2001/XMLSchema ); p1.schemaType = stype; p2.schemaType = stype; soapcall.encode( 0, //wartość domyślna dla protokołu SOAP 1.1 DivideNumbers , //nazwa metody sieciowej http://hauser-wenz.de/AspNetAJAX/ , //przestrzeń nazw 0, //liczba dodatkowych nagłówków new Array( ), //dodatkowe nagłówki 2, //liczba parametrów new Array(p1, p2) //parametry ); soapcall.asyncInvoke(callComplete); } function callComplete(result, soapcall, status) { document.getElementById( c ).innerHTML = result.body.firstChild.firstChild.firstChild.data; } /script /head body form method= post onsubmit= return false; div nobr input type= text id= a name= a size= 2 / : input type= text id= b name= b size= 2 / = span id= c style= width: 50px; /span /nobr br / input type= button value= Podziel liczby onclick= callService(this.form); / /div /form /body /html Usługi sieciowe w obydwu przeglądarkach Przegląd technik korzystania z usług sieciowych z poziomu skryptu JavaScript w przeglą- darkach Internet Explorer i Mozilla zakończymy rozwiązaniem, które łączy obydwie metody na jednej stronie. W tym celu musimy przede wszystkim ustalić, w jaki sposób rozpoznawa- ny będzie rodzaj przeglądarki. Zgodnie z informacjami zamieszczonymi w rozdziale 2, naj- korzystniejsze wydaje się sprawdzenie zestawu funkcji przeglądarki, a nie ich typu. Zasada ta została wykorzystana podczas opracowywania kodu z przykładu 5.9 (jej opis znajduje się w rozdziale 2, w części dotyczącej powoływania obiektu XMLHttpRequest). Rozwiązanie po- lega na utworzeniu obiektu właściwego dla jednej przeglądarki. Jeśli to się uda, dalsza część kodu zostanie wykonana zgodnie z założeniami. W przeciwnym przypadku wykorzystane zostaną instrukcje właściwe dla drugiej przeglądarki. Poszczególne wywołania zostały za- pisane w dwóch zagnieżdżonych konstrukcjach try … catch. Wykorzystanie usług sieciowych z poziomu skryptu JavaScript | 125 Dostęp do zdalnych usług sieciowych w przeglądarkach Mozilla Model zabezpieczeń przeglądarki Mozilla umożliwia odwołania do zdalnych usług sieciowych. Wykonanie skryptu wiąże się jednak z wyświetleniem okna dialogowego, w którym użyt- kownik musi zezwolić na taką operację (rysunek 5.7). Wymagane jest w tym przypadku uprawnienie UniversalBrowserRead, oznaczające, że przeglądarka może pobierać dane z dowolnego serwera (włączając w to zarówno serwery zdalne, jak i lokalny system plików). netscape.security.PrivilegeManager.enablePrivilege( UniversalBrowserRead ); Rysunek 5.7. Żądanie zwiększenia poziomu uprawnień w przeglądarce Firefox Domyślna konfiguracja przeglądarek Mozilla i Firefox (a także kilku innych) powoduje na- danie wspomnianego uprawnienia tylko w dostępie do plików lokalnych (z definicją protokołu file://). Mechanizm ten znajduje więc zastosowanie głównie w aplikacjach intranetowych. Wygląd okna dialogowego z żądaniem zwiększenia poziomu uprawnień został pokazany na rysunku 5.7. Przykład 5.9. Wywołanie usługi sieciowej w dowolnej z przeglądarek Internet Explorer i Mozilla MathService.htm !DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd html xmlns= http://www.w3.org/1999/xhtml head title ASP.NET AJAX /title script language= Javascript type= text/javascript function callService(f) { document.getElementById( c ).innerHTML = ; try { WebService.useService( MathService.asmx?WSDL , MathService ); WebService.MathService.callService( callComplete, DivideNumbers , parseInt(f.elements[ a ].value), parseInt(f.elements[ b ].value)); } catch (e) { try { var soapcall = new SOAPCall( ); soapcall.actionURI = http://hauser-wenz.de/AspNetAJAX/DivideNumbers ; 126 | Rozdział 5. Usługi sieciowe soapcall.transportURI = http://localhost:1041/AJAXEnabledWebSite1/ MathService.asmx ; var p1 = new SOAPParameter(parseInt(f.elements[ a ].value), a ); var p2 = new SOAPParameter(parseInt(f.elements[ b ].value), b ); var senc = new SOAPEncoding( ); assenc = senc.getAssociatedEncoding( http://schemas.xmlsoap.org/soap/encoding/ , false); var scoll = assenc.schemaCollection; var stype = scoll.getType( integer , http://www.w3.org/2001/XMLSchema ); p1.schemaType = stype; p2.schemaType = stype; soapcall.encode( 0, //wartość domyślna dla protokołu SOAP 1.1 DivideNumbers , //nazwa metody sieciowej http://hauser-wenz.de/AspNetAJAX/ , //przestrzeń nazw 0, //liczba dodatkowych nagłówków new Array( ), //dodatkowe nagłówki 2, //liczba parametrów new Array(p1, p2) //parametry ); soapcall.asyncInvoke(callComplete); } catch (e) { window.alert( Twoja przeglądarka nie jest obsługiwana. ); } } } function callComplete(result, soapcall, status) { if (result.value != null) { document.getElementById( c ).innerHTML = result.value; } else { document.getElementById( c ).innerHTML = result.body.firstChild.firstChild.firstChild.data; } } /script /head body div id= WebService style= behavior: url(webservice.htc); /div form method= post onsubmit= return false; div nobr input type= text id= a name= a size= 2 / : input type= text id= b name= b size= 2 / = span id= c style= width: 50px; /span /nobr br / input type= button value= Podziel liczby onclick= callService(this.form); / /div /form /body /html Wykorzystanie usług sieciowych z poziomu skryptu JavaScript | 127 W przykładzie 5.9 zostały zamieszczone wszystkie znaczniki i instrukcje skryptowe, które pozwalają na wykonanie zadania. Nie zmienia to faktu, że przed wdrożeniem aplikacji trzeba ją przetestować również w innych przeglądarkach. Należy również pamiętać o przypisaniu właściwości soapcall.transportURI poprawnego adresu URL witryny (włącznie z numerem portu, jeśli jest to konieczne). Jak można się przekonać, analizując rysunki 5.8 i 5.9, opracowana aplikacja działa poprawnie w dwóch najpowszechniej stosowanych przeglądarkach. Rysunek 5.8. Wykonanie skryptu w przeglądarce Internet Explorer Rysunek 5.9. Wykonanie skryptu w przeglądarkach Mozilla, a dokładniej w przeglądarce Firefox 128 | Rozdział 5. Usługi sieciowe Pozostaje jeszcze tylko problem ustalenia, czy uzyskany efekt jest wart dodatkowej pracy. Czy rzeczywiście przygotowanie niezbyt uniwersalnego rozwiązania do wywoływania usług sieciowych można określić jako użyteczne? Witryny bazujące na platformie ASP.NET reali- zują takie zadania bezproblemowo z wykorzystaniem kodu ASP.NET AJAX. Biorąc pod uwagę łatwość wdrażania aplikacji ASP.NET AJAX, metoda opisana w tym punkcie powinna być postrzegana jako „ostatnia deska ratunku” (szczególnie jeśli uwzględnimy wstrzymanie prac nad rozwojem usług sieciowych w oprogramowaniu Mozilla). Podsumowanie W niniejszym rozdziale zostało opisanych kilka sposobów wykorzystania usług sieciowych. W pierwszym podrozdziale zostały omówione zagadnienia związane z obsługą błędów i prze- chowywaniem danych w sesji. Kolejne punkty zawierają przykłady wymiany złożonych da- nych między aplikacjami klienckimi i usługami sieciowymi, a także przykłady rozwiązań umożliwiających wywoływanie z poziomu skryptu JavaScript usług sieciowych udostępnio- nych na serwerach innych niż ASP.NET. Do dalszego czytania http://msdn.microsoft.com/archive/en-us/samples/internet/behaviors/library/webservice/default.asp Wcześniejsze wersje kontrolki webservice.htc. http://ajax.asp.net/docs/tutorials/ASPNETAJAXWebServicesTutorials.aspx Przewodnik dotyczący usług sieciowych w dokumentacji Microsoft ASP.NET AJAX. Do dalszego czytania | 129
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

ASP.NET AJAX. Programowanie w nurcie Web 2.0
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: