informatyka asp net ajax programowanie w nurcie web 2 0 christian wenz ebook

background image

Wydawnictwo Helion
ul. Koœciuszki 1c
44-100 Gliwice
tel. 032 230 98 63

e-mail: helion@helion.pl

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órz interaktywn¹ stronê internetow¹

Jak wykorzystywaæ dane serwerowe?

Jak tworzyæ i udostêpniaæ w³asne kontrolki?

Jak aktualizowaæ czêœæ strony w regularnych odstêpach czasu?

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.

Struktura i architektura œrodowiska ASP.NET AJAX

JavaScript

Rozszerzenia ASP.NET AJAX

Us³ugi sieciowe

Odœwie¿anie czêœci strony — obiekt UpdatePanel

Lokalizacja i globalizacja aplikacji

ASP.NET Control Toolkit

Animacja na stronie WWW

Wi¹zanie i walidacja danych

Zachowania i komponenty

Dokumentacja klasy XMLHttpRequest i modelu DOM

P³yñ z nurtem nowoczesnoœci — twórz elektryzuj¹ce, interaktywne strony WWW!

background image

3

Spis tre

ļci

Przedmowa ...............................................................................................................................9

I Podstawy ................................................................................................ 17

1. ASP.NET AJAX, Ajax i ASP.NET .................................................................................... 19

ASP.NET AJAX i Ajax

19

ASP.NET AJAX i ASP.NET

21

Wymagania wstöpne i instalacja ASP.NET AJAX

23

Struktura i architektura Ĉrodowiska ASP.NET AJAX

29

Pierwszy przykäad strony ASP.NET AJAX — Witaj uĔytkowniku

31

Kontrolka ScriptManager

35

Podsumowanie

37

Do dalszego czytania

37

2. JavaScript .....................................................................................................................39

Jözyk JavaScript

41

Programowanie obiektowe

51

Dostöp do elementów strony

54

Metody modelu DOM

58

Podsumowanie

59

Do dalszego czytania

59

3. Ajax .............................................................................................................................. 61

Obiekt XMLHttpRequest

61

Obiekt XMLDocument

71

JSON

76

Podsumowanie

79

Do dalszego czytania

79

background image

4

_ Spis treļci

II Rozszerzenia ASP.NET AJAX ..................................................................81

4. Wykorzystanie rozszerze

ħ JavaScript ļrodowiska ASP.NET AJAX ...........................83

Skróty ASP.NET AJAX i funkcje pomocnicze

83

Rozszerzenia istniejñcych obiektów JavaScript

86

Techniki programowania obiektowego dla jözyka JavaScript w ASP.NET AJAX

87

Klienckie wersje klas .NET

98

Podsumowanie

102

Do dalszego czytania

102

5. Us

ĥugi sieciowe .......................................................................................................... 103

Obsäuga bäödów

103

Metody strony

107

Przechowywanie informacji o stanie sesji

110

Wymiana zäoĔonych struktur danych miödzy klientem i serwerem

115

Wykorzystanie usäug sieciowych z poziomu skryptu JavaScript

119

Podsumowanie

129

Do dalszego czytania

129

6. Od

ļwieżanie czýļci strony — obiekt UpdatePanel ..................................................131

Przeksztaäcenie fragmentu strony w aktualizowany obszar

132

Podsumowanie

145

Do dalszego czytania

146

7. Wykorzystanie us

ĥugi profili ASP.NET AJAX ............................................................ 147

Przygotowanie witryny

148

Dostöp do danych profilu

149

Dostöp do danych profilu zdefiniowanych w grupie

154

Podsumowanie

158

Do dalszego czytania

158

8. Wykorzystanie us

ĥugi uwierzytelniania ASP.NET AJAX .......................................... 159

Przygotowanie aplikacji

159

Logowanie i wylogowanie

162

Podsumowanie

168

Do dalszego czytania

168

9. Lokalizacja i globalizacja aplikacji ............................................................................ 169

Lokalizacja

170

Globalizacja i internacjonalizacja

182

Podsumowanie

186

Do dalszego czytania

186

background image

Spis tre

ļci

_

5

III ASP.NET AJAX Control Toolkit ............................................................. 187

10. Korzystanie z pakietu Control Toolkit ...................................................................... 189

Instalacja pakietu Control Toolkit

189

Korzystanie z pakietu kontrolek

192

Podsumowanie

195

Do dalszego czytania

195

11. Animacja na stronie WWW ....................................................................................... 197

Platforma animacji

197

Mechanizm „przeciñgnij i upuĈè”

204

Podsumowanie

207

Do dalszego czytania

207

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

Dynamiczne zwijanie pojedynczego panelu

221

WyĈwietlanie okna komunikatu

223

Zwalczanie spamu w blogach i na innych forach internetowych

226

Tworzenie zakäadek

228

Podsumowanie

230

Do dalszego czytania

230

13. Tworzenie i udost

ýpnianie wĥasnych kontrolek ...................................................... 231

Tworzenie wäasnych kontrolek ASP.NET AJAX

231

Doäñczenie komponentu do pakietu Control Toolkit

239

Podsumowanie

247

Do dalszego czytania

248

IV ASP.NET AJAX Futures ......................................................................... 249

14. Kontrolki klienckie ..................................................................................................... 251

Podstawy korzystania z kontrolek klienckich ASP.NET AJAX

251

Korzystanie z kontrolek ASP.NET AJAX

252

Obsäuga zdarzeþ kontrolek

267

Podsumowanie

271

Do dalszego czytania

271

background image

6

_ Spis treļci

15. Wi

ézanie i walidacja danych ....................................................................................273

Wiñzanie danych

273

Walidacja danych

289

Podsumowanie

303

Do dalszego czytania

303

16. Zachowania i komponenty ........................................................................................305

Wykorzystanie zachowaþ

305

Wykorzystanie komponentów

317

Podsumowanie

319

Do dalszego czytania

319

17. Wykorzystanie danych serwerowych ...................................................................... 321

Kontrolka ListView

321

Utworzenie wäasnego Ēródäa danych

336

Podsumowanie

341

Do dalszego czytania

341

18. Animacje ....................................................................................................................343

Zastosowanie animacji

343

Wykorzystanie animacji do uzyskania efektu zanikania

344

Podsumowanie

354

Do dalszego czytania

354

19. Usprawnianie dzia

ĥania zakĥadek oraz przycisków „w przód” i „w tyĥ” ...............355

Poprawianie kodu

356

Usprawnianie zakäadek oraz przycisków „w przód” i „w tyä”
za pomocñ kontrolki UpdateHistory

358

Usprawnianie zakäadek oraz przycisków „w przód” i „w tyä”
za pomocñ kontrolek ASP.NET AJAX Futures

362

Podsumowanie

368

Do dalszego czytania

368

20. Rozszerzenie Web Parts ............................................................................................369

Wykorzystanie Ĉrodowiska ASP.NET AJAX z rozszerzeniem ASP.NET Web Parts 369
Podsumowanie

374

Do dalszego czytania

374

background image

Spis tre

ļci

_

7

V Biblioteka Microsoft AJAX ...................................................................375

21. Wykorzystanie ASP.NET AJAX w po

ĥéczeniu z innymi technologiami sieciowymi ......377

Wykorzystanie rozwiñzaþ ASP.NET AJAX w aplikacji PHP

378

Podsumowanie

382

Do dalszego czytania

382

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

background image

103

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.

background image

104

_

Rozdzia

ĥ 5. Usĥugi sieciowe

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>

background image

Obs

ĥuga bĥýdów

_ 105

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.

background image

106

_

Rozdzia

ĥ 5. Usĥugi sieciowe

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>

background image

Metody strony

_ 107

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.

background image

108

_

Rozdzia

ĥ 5. Usĥugi sieciowe

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:

x

Metoda musi byè oznaczona za pomocñ atrybutu

ScriptMethod

, opisanego w przestrzeni

nazw

System.Web.Script.Services

.

x

Metoda musi byè zadeklarowana jako publiczna (

public

).

x

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" />

background image

Metody strony

_ 109

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"

background image

110

_

Rozdzia

ĥ 5. Usĥugi sieciowe

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.

background image

Przechowywanie informacji o stanie sesji

_ 111

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 :-)
}

background image

112

_

Rozdzia

ĥ 5. Usĥugi sieciowe

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()
{

background image

Przechowywanie informacji o stanie sesji

_ 113

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 {

background image

114

_

Rozdzia

ĥ 5. Usĥugi sieciowe

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

background image

Wymiana z

ĥożonych struktur danych miýdzy klientem i serwerem

_ 115

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;

background image

116

_

Rozdzia

ĥ 5. Usĥugi sieciowe

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

background image

Wymiana z

ĥożonych struktur danych miýdzy klientem i serwerem

_ 117

{
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>

background image

118

_

Rozdzia

ĥ 5. Usĥugi sieciowe

<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).

background image

Wykorzystanie us

ĥug sieciowych z poziomu skryptu JavaScript

_ 119

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

).

background image

120

_

Rozdzia

ĥ 5. Usĥugi sieciowe

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");

background image

Wykorzystanie us

ĥug sieciowych z poziomu skryptu JavaScript

_ 121

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:

x

referencja do metody zwrotnej,

x

nazwa wywoäywanej metody sieciowej,

x

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>

background image

122

_

Rozdzia

ĥ 5. Usĥugi sieciowe

<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).

background image

Wykorzystanie us

ĥug sieciowych z poziomu skryptu JavaScript

_ 123

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:

x

dokument XML bödñcy wynikiem wywoäania usäugi sieciowej,

x

obiekt

SOAPCall

(gdyby konieczne byäo przeanalizowanie nagäówków SOAP),

x

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>

background image

124

_

Rozdzia

ĥ 5. Usĥugi sieciowe

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:

x

odwoäania siö do wäaĈciwoĈci

body

, która zapewni dostöp do elementu

<soap:Body>

;

x

odwoäania siö do wäaĈciwoĈci

firstChild

, która zapewni dostöp do elementu

<Divide-

NumbersResponse>

;

x

ponownego wykorzystania wäaĈciwoĈci

firstChild

do pobrania elementu

<DivideNum-

bersResult>

;

x

wykorzystania po raz trzeci wäaĈciwoĈci

firstChild

, aby uzyskaè dostöp do wözäa tek-

stowego w elemencie

<DivideNumbersResult>

;

x

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",

background image

Wykorzystanie us

ĥug sieciowych z poziomu skryptu JavaScript

_ 125

"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

.

background image

126

_

Rozdzia

ĥ 5. Usĥugi sieciowe

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";

background image

Czytaj dalej...

Wykorzystanie us

ĥug sieciowych z poziomu skryptu JavaScript

_ 127

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>


Wyszukiwarka

Podobne podstrony:
ASPNET AJAX Programowanie w nurcie Web 20
informatyka asp net mvc 4 programowanie jess chadwick ebook
ASP NET AJAX Server Controls Zaawansowane programowanie w nurcie NET Framework 3 5 Microsoft NET Dev
informatyka asp net 3 5 tworzenie portali internetowych w nurcie web 2 0 omar al zabir ebook

więcej podobnych podstron