Objaśnienie usług internetowych ASP.NET AJAX
Autor: Scott Cate
Usługi sieci Web są integralną częścią platformy .NET, która zapewnia międzyplatformowe rozwiązanie do wymiany danych między systemami rozproszonymi. Chociaż usługi sieci Web są zwykle używane do zezwalania na różne systemy operacyjne, modele obiektów i języki programowania do wysyłania i odbierania danych, mogą być również używane do dynamicznego wstrzykiwania danych do strony ASP.NET AJAX lub wysyłania danych ze strony do systemu zaplecza. Wszystko to można zrobić bez uciekania się do operacji ogłaszania zwrotnego.
Wywoływanie usług sieci Web za pomocą ASP.NET AJAX
Dan Wahlin
Usługi sieci Web są integralną częścią platformy .NET, która zapewnia międzyplatformowe rozwiązanie do wymiany danych między systemami rozproszonymi. Chociaż usługi sieci Web są zwykle używane do zezwalania na różne systemy operacyjne, modele obiektów i języki programowania do wysyłania i odbierania danych, mogą być również używane do dynamicznego wstrzykiwania danych do strony ASP.NET AJAX lub wysyłania danych ze strony do systemu zaplecza. Wszystko to można zrobić bez uciekania się do operacji ogłaszania zwrotnego.
Podczas gdy kontrolka ASP.NET UpdatePanel AJAX zapewnia prosty sposób włączania dowolnej strony ASP.NET, mogą wystąpić czasy, gdy trzeba dynamicznie uzyskiwać dostęp do danych na serwerze bez użycia kontrolki UpdatePanel. W tym artykule dowiesz się, jak to zrobić, tworząc i korzystając z usług internetowych na stronach ASP.NET AJAX.
W tym artykule skoncentrujemy się na funkcjach dostępnych w podstawowych rozszerzeniach AJAX ASP.NET, a także na kontrolce z włączoną usługą internetową w zestawie narzędzi ASP.NET AJAX o nazwie AutoCompleteExtender. Omówione tematy obejmują definiowanie usług sieci Web z obsługą technologii AJAX, tworzenie serwerów proxy klienta i wywoływanie usług internetowych za pomocą języka JavaScript. Zobaczysz również, jak wywołania usługi sieci Web można wykonywać bezpośrednio w celu ASP.NET metod stron.
Konfiguracja usług sieci Web
Po utworzeniu nowego projektu witryny sieci Web za pomocą programu Visual Studio 2008 plik web.config zawiera szereg nowych dodatków, które mogą być nieznane użytkownikom poprzednich wersji programu Visual Studio. Niektóre z tych modyfikacji mapują prefiks "asp", aby ASP.NET kontrolki AJAX, aby mogły być używane na stronach, podczas gdy inne definiują wymagane procedury obsługi http i moduły HttpModules. Lista 1 pokazuje modyfikacje wprowadzone do <httpHandlers>
elementu w pliku web.config, które wpływają na wywołania usługi sieci Web. Domyślna procedura HttpHandler używana do przetwarzania wywołań asmx jest usuwana i zastępowana klasą ScriptHandlerFactory znajdującą się w zestawie System.Web.Extensions.dll. System.Web.Extensions.dll zawiera wszystkie podstawowe funkcje używane przez ASP.NET AJAX.
Lista 1. konfiguracja programu obsługi usługi internetowej ASP.NET AJAX
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
</httpHandlers>
To zastąpienie programu HttpHandler jest wykonywane w celu umożliwienia wywołań w formacie JavaScript Object Notation (JSON) z ASP.NET stron AJAX do usług sieci Web platformy .NET przy użyciu serwera proxy usługi sieci Web JavaScript. ASP.NET AJAX wysyła komunikaty JSON do usług sieci Web, a nie standardowe wywołania protokołu SIMPLE Object Access Protocol (SOAP) zwykle skojarzone z usługami sieci Web. Powoduje to ogólne zmniejszenie liczby komunikatów dotyczących żądań i odpowiedzi. Umożliwia również wydajniejsze przetwarzanie danych po stronie klienta, ponieważ biblioteka javaScript AJAX ASP.NET jest zoptymalizowana pod kątem pracy z obiektami JSON. Lista 2 i Lista 3 pokazują przykłady komunikatów usługi sieci Web i odpowiedzi serializowane do formatu JSON. Komunikat żądania wyświetlany w liście 2 przekazuje parametr kraju z wartością "Belgia", podczas gdy komunikat odpowiedzi w liście 3 przekazuje tablicę obiektów klienta i skojarzonych z nimi właściwości.
Lista 2. Komunikat żądania usługi sieci Web serializowany do formatu JSON
{"country":"Belgium"}
> [! UWAGA] nazwa operacji jest zdefiniowana jako część adresu URL usługi internetowej; ponadto komunikaty żądań nie zawsze są przesyłane za pośrednictwem formatu JSON. Usługi sieci Web mogą używać atrybutu ScriptMethod z parametrem UseHttpGet ustawionym na true, co powoduje przekazanie parametrów za pośrednictwem parametrów ciągu zapytania.
Lista 3. Komunikat odpowiedzi usługi sieci Web serializowany do formatu JSON
[{"__type":"Model.Customer","Country":"Belgium","CompanyName":"Maison
Dewey","CustomerID":"MAISD","ContactName":"Catherine
Dewey"},{"__type":"Model.Customer","Country":"Belgium","CompanyName":"Suprêmes
délices","CustomerID":"SUPRD","ContactName":"Pascale
Cartrain"}]
W następnej sekcji dowiesz się, jak utworzyć usługi sieci Web umożliwiające obsługę komunikatów żądań JSON i odpowiadać zarówno przy użyciu prostych, jak i złożonych typów.
Tworzenie usług sieci Web z obsługą technologii AJAX
Platforma ASP.NET AJAX oferuje kilka różnych sposobów wywoływania usług sieci Web. Możesz użyć kontrolki AutoCompleteExtender (dostępnej w zestawie narzędzi ASP.NET AJAX) lub JavaScript. Jednak przed wywołaniem usługi należy ją włączyć AJAX, aby można było ją wywołać za pomocą kodu skryptu klienta.
Niezależnie od tego, czy dopiero zaczynasz ASP.NET usługami sieci Web, możesz łatwo tworzyć i włączać usługi AJAX. Platforma .NET Framework obsługuje tworzenie usług sieci Web ASP.NET od czasu jej początkowej wersji w 2002 r., a rozszerzenia ASP.NET AJAX zapewniają dodatkowe funkcje AJAX, które opierają się na domyślnym zestawie funkcji platformy .NET Framework. Program Visual Studio .NET 2008 Beta 2 ma wbudowaną obsługę tworzenia plików usługi sieci Web asmx i automatycznie uzyskuje skojarzony kod obok klas z klasy System.Web.Services.WebService. Podczas dodawania metod do klasy należy zastosować atrybut WebMethod, aby były wywoływane przez użytkowników usługi sieci Web.
Na liście 4 przedstawiono przykład zastosowania atrybutu WebMethod do metody o nazwie GetCustomersByCountry().
Lista 4. Używanie atrybutu WebMethod w usłudze sieci Web
[WebMethod]
public Customer[] GetCustomersByCountry(string country)
{
return Biz.BAL.GetCustomersByCountry(country);
}
Metoda GetCustomersByCountry() akceptuje parametr kraju i zwraca tablicę obiektów Customer. Wartość kraju przekazana do metody jest przekazywana do klasy warstwy biznesowej, która z kolei wywołuje klasę warstwy danych, aby pobrać dane z bazy danych, wypełnić właściwości obiektu Klient danymi i zwrócić tablicę.
Używanie atrybutu ScriptService
Dodanie atrybutu WebMethod umożliwia wywołanie metody GetCustomersByCountry() przez klientów wysyłających standardowe komunikaty PROTOKOŁU SOAP do usługi sieci Web, nie zezwala na wykonywanie wywołań JSON z aplikacji AJAX ASP.NET gotowe. Aby zezwolić na wykonywanie wywołań JSON, należy zastosować atrybut rozszerzenia ScriptService
AJAX ASP.NET do klasy usługi sieci Web. Umożliwia to usłudze sieci Web wysyłanie komunikatów odpowiedzi sformatowanych przy użyciu formatu JSON i umożliwia wywoływanie usługi przez wysyłanie komunikatów JSON po stronie klienta.
Na liście 5 przedstawiono przykład zastosowania atrybutu ScriptService do klasy usługi internetowej o nazwie CustomersService.
Lista 5. Używanie atrybutu ScriptService do włączania usługi internetowej AJAX
[System.Web.Script.Services.ScriptService]
[WebService(Namespace = "http://xmlforasp.net")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class CustomersService : System.Web.Services.WebService
{
[WebMethod]
public Customer[] GetCustomersByCountry(string country)
{
return Biz.BAL.GetCustomersByCountry(country);
}
}
Atrybut ScriptService działa jako znacznik, który wskazuje, że może być wywoływany z kodu skryptu AJAX. W rzeczywistości nie obsługuje żadnego z zadań serializacji JSON ani deserializacji, które występują w tle. SkryptHandlerFactory (skonfigurowany w pliku web.config) i inne powiązane klasy wykonują większość przetwarzania JSON.
Używanie atrybutu ScriptMethod
Atrybut ScriptService jest jedynym atrybutem AJAX ASP.NET, który musi być zdefiniowany w usłudze sieci Web platformy .NET, aby był używany przez strony AJAX ASP.NET. Jednak inny atrybut o nazwie ScriptMethod można również zastosować bezpośrednio do metod sieci Web w usłudze. ScriptMethod definiuje trzy właściwości, w tym UseHttpGet
, ResponseFormat
i XmlSerializeString
. Zmiana wartości tych właściwości może być przydatna w przypadkach, gdy typ żądania zaakceptowanego przez metodę sieci Web musi zostać zmieniony na GET, gdy metoda sieci Web musi zwrócić nieprzetworzone dane XML w postaci XmlDocument
obiektu lub XmlElement
lub gdy dane zwrócone z usługi powinny być zawsze serializowane jako XML zamiast JSON.
Właściwość UseHttpGet może być używana, gdy metoda sieci Web powinna akceptować żądania GET w przeciwieństwie do żądań POST. Żądania są wysyłane przy użyciu adresu URL z parametrami wejściowymi metody internetowej przekonwertowanymi na parametry QueryString. Właściwość UseHttpGet domyślnie ma wartość false i powinna być ustawiona true
tylko wtedy, gdy operacje są znane jako bezpieczne i gdy poufne dane nie są przekazywane do usługi sieci Web. Na liście 6 przedstawiono przykład użycia atrybutu ScriptMethod z właściwością UseHttpGet.
Lista 6. Za pomocą atrybutu ScriptMethod z właściwością UseHttpGet.
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public string HttpGetEcho(string input)
{
return input;
}
Przykład nagłówków wysyłanych po wywołaniu metody sieci Web HttpGetEcho wyświetlanej na liście 6:
GET /CustomerViewer/DemoService.asmx/HttpGetEcho?input=%22Input Value%22 HTTP/1.1
Oprócz umożliwienia metod sieci Web akceptowania żądań HTTP GET atrybut ScriptMethod może być również używany, gdy odpowiedzi XML muszą być zwracane z usługi, a nie z formatu JSON. Na przykład usługa sieci Web może pobrać źródło danych RSS ze zdalnej witryny i zwrócić je jako obiekt XmlDocument lub XmlElement. Przetwarzanie danych XML może nastąpić na kliencie.
Na liście 7 przedstawiono przykład użycia właściwości ResponseFormat w celu określenia, że dane XML powinny być zwracane z metody sieci Web.
Lista 7. Za pomocą atrybutu ScriptMethod z właściwością ResponseFormat.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
public XmlElement GetRssFeed(string url)
{
XmlDocument doc = new XmlDocument();
doc.Load(url);
return doc.DocumentElement;
}
Właściwość ResponseFormat może być również używana wraz z właściwością XmlSerializeString. Właściwość XmlSerializeString ma wartość domyślną false, co oznacza, że wszystkie typy zwracane z wyjątkiem ciągów zwracanych z metody sieci Web są serializowane jako XML, gdy ResponseFormat
właściwość jest ustawiona na ResponseFormat.Xml
. Gdy XmlSerializeString
jest ustawiona wartość true
, wszystkie typy zwracane z metody sieci Web są serializowane jako XML, w tym typy ciągów. Jeśli właściwość ResponseFormat ma wartość ResponseFormat.Json
właściwości XmlSerializeString, jest ignorowana.
Lista 8 przedstawia przykład użycia właściwości XmlSerializeString w celu wymuszenia serializacji ciągów jako XML.
Lista 8. Używanie atrybutu ScriptMethod z właściwością XmlSerializeString
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml,XmlSerializeString=true)]
public string GetXmlString(string input)
{
return input;
}
Wartość zwrócona z wywołania metody sieci Web GetXmlString pokazanej w liście 8 jest wyświetlana w następnej kolejności:
<?xml version="1.0"?>
<string>Test</string>
Mimo że domyślny format JSON minimalizuje ogólny rozmiar komunikatów żądań i odpowiedzi i jest bardziej czytelnie używany przez klientów ASP.NET AJAX w sposób między przeglądarkami, właściwości ResponseFormat i XmlSerializeString można wykorzystać, gdy aplikacje klienckie, takie jak Internet Explorer 5 lub nowsze, oczekują, że dane XML będą zwracane z metody sieci Web.
Praca z typami złożonymi
Na liście 5 przedstawiono przykład zwracania typu złożonego o nazwie Klient z usługi internetowej. Klasa Customer definiuje kilka różnych prostych typów wewnętrznie, takich jak FirstName i LastName. Typy złożone używane jako parametr wejściowy lub zwracany typ metody sieci Web z obsługą AJAX są automatycznie serializowane w formacie JSON przed wysłaniem do strony klienta. Jednak zagnieżdżone typy złożone (zdefiniowane wewnętrznie w ramach innego typu) nie są domyślnie udostępniane klientowi jako obiekty autonomiczne.
W przypadkach, gdy zagnieżdżony typ złożony używany przez usługę sieci Web musi być również używany na stronie klienta, ASP.NET można dodać atrybut AJAX GenerateScriptType do usługi sieci Web. Na przykład klasa CustomerDetails wyświetlana na liście Listing 9 zawiera właściwości Address (Adres) i Gender (Płeć), które reprezentują zagnieżdżone typy złożone.
Lista 9. Pokazana tutaj klasa CustomerDetails zawiera dwa zagnieżdżone typy złożone.
public class CustomerDetails : Customer
{
public CustomerDetails()
{
}
Address _Address;
Gender _Gender = Gender.Unknown;
public Address Address
{
get { return _Address; }
set { _Address = value; }
}
public Gender Gender
{
get { return _Gender; }
set { _Gender = value; }
}
}
Obiekty Address and Gender zdefiniowane w klasie CustomerDetails pokazane w liście 9 nie zostaną automatycznie udostępnione do użycia po stronie klienta za pośrednictwem języka JavaScript, ponieważ są one zagnieżdżone typy (Adres jest klasą, a płeć jest wyliczeniem). W sytuacjach, gdy zagnieżdżony typ używany w usłudze sieci Web musi być dostępny po stronie klienta, można użyć atrybutu GenerateScriptType wymienionego wcześniej (zobacz Lista 10). Ten atrybut można dodać wiele razy w przypadkach, gdy różne zagnieżdżone typy złożone są zwracane z usługi. Można ją zastosować bezpośrednio do klasy usługi sieci Web lub powyżej określonych metod sieci Web.
Lista 10. Za pomocą atrybutu GenerateScriptService zdefiniuj zagnieżdżone typy, które powinny być dostępne dla klienta.
[System.Web.Script.Services.ScriptService]
[System.Web.Script.Services.GenerateScriptType(typeof(Address))]
[System.Web.Script.Services.GenerateScriptType(typeof(Gender))]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class NestedComplexTypeService : System.Web.Services.WebService
{
//Web Methods
}
GenerateScriptType
Stosując atrybut do usługi internetowej, typy adresów i płci zostaną automatycznie udostępnione do użycia przez kod JavaScript po stronie klienta ASP.NET AJAX. Przykład kodu JavaScript, który jest generowany automatycznie i wysyłany do klienta przez dodanie atrybutu GenerateScriptType w usłudze sieci Web, jest wyświetlany na liście 11. W dalszej części artykułu zobaczysz, jak używać zagnieżdżonych typów złożonych.
Lista 11. Zagnieżdżone typy złożone udostępnione ASP.NET stronie AJAX.
if (typeof(Model.Address) === 'undefined')
{
Model.Address=gtc("Model.Address");
Model.Address.registerClass('Model.Address');
}
Model.Gender = function() { throw Error.invalidOperation(); }
Model.Gender.prototype = {Unknown: 0,Male: 1,Female: 2}
Model.Gender.registerEnum('Model.Gender', true);
Teraz, gdy już wiesz, jak utworzyć usługi sieci Web i udostępnić je ASP.NET stron AJAX, przyjrzyjmy się sposobom tworzenia i używania serwerów proxy języka JavaScript, dzięki czemu dane można pobrać lub wysłać do usług sieci Web.
Tworzenie serwerów proxy języka JavaScript
Wywoływanie standardowej usługi internetowej (.NET lub innej platformy) zwykle polega na utworzeniu obiektu proxy, który chroni przed złożonością wysyłania komunikatów żądań i odpowiedzi protokołu SOAP. Za pomocą ASP.NET wywołań usługi internetowej AJAX można tworzyć serwery proxy JavaScript i używać ich do łatwego wywoływania usług bez obaw o serializowanie i deserializacji komunikatów JSON. Serwery proxy języka JavaScript mogą być generowane automatycznie przy użyciu kontrolki ASP.NET AJAX ScriptManager.
Tworzenie serwera proxy języka JavaScript, który może wywoływać usługi sieci Web, jest realizowane przy użyciu właściwości Usług ScriptManager. Ta właściwość umożliwia zdefiniowanie co najmniej jednej usługi, którą strona AJAX ASP.NET może wywołać asynchronicznie, aby wysyłać lub odbierać dane bez konieczności wykonywania operacji ogłaszania zwrotnego. Usługę można zdefiniować przy użyciu kontrolki ASP.NET AJAX ServiceReference
i przypisywać adres URL usługi internetowej do właściwości kontrolki Path
. Na liście 12 przedstawiono przykład odwoływania się do usługi o nazwie CustomersService.asmx.
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/CustomersService.asmx" />
</Services>
</asp:ScriptManager>
Lista 12. Definiowanie usługi internetowej używanej na stronie ASP.NET AJAX.
Dodanie odwołania do pliku CustomersService.asmx za pomocą kontrolki ScriptManager powoduje dynamiczne generowanie i odwoływania się do serwera proxy języka JavaScript przez stronę. Serwer proxy jest osadzony przy użyciu tagu skryptu <> i dynamicznie ładowany przez wywołanie pliku CustomersService.asmx i dołączenie /js na końcu. W poniższym przykładzie pokazano, jak serwer proxy języka JavaScript jest osadzony na stronie, gdy debugowanie jest wyłączone w pliku web.config:
<script src="CustomersService.asmx/js" type="text/javascript"></script>
> [! UWAGA] Jeśli chcesz zobaczyć rzeczywisty kod serwera proxy JavaScript, który jest generowany, możesz wpisać adres URL do żądanej usługi internetowej .NET w polu adresu programu Internet Explorer i dołączyć /js na końcu.
Jeśli debugowanie jest włączone w pliku web.config, wersja debugowania serwera proxy języka JavaScript zostanie osadzona na stronie, jak pokazano poniżej:
<script src="CustomersService.asmx/jsdebug" type="text/javascript"></script>
Serwer proxy języka JavaScript utworzony przez narzędzie ScriptManager można również osadzać bezpośrednio na stronie, a nie przy użyciu <atrybutu src tagu skryptu> . Można to zrobić, ustawiając właściwość InlineScript kontrolki ServiceReference na true (wartość domyślna to false). Może to być przydatne, gdy serwer proxy nie jest współużytkowany na wielu stronach i gdy chcesz zmniejszyć liczbę wywołań sieciowych wykonanych na serwerze. Jeśli w tekścieScript ustawiono wartość true, skrypt serwera proxy nie będzie buforowany przez przeglądarkę, dlatego wartość domyślna false jest zalecana w przypadkach, gdy serwer proxy jest używany przez wiele stron w aplikacji AJAX ASP.NET. Poniżej przedstawiono przykład użycia właściwości InlineScript:
<asp:ServiceReference InlineScript="true" Path="~/CustomersService.asmx"/>
Korzystanie z serwerów proxy języka JavaScript
Po odwoływaniu się do usługi sieci Web przez stronę ASP.NET AJAX przy użyciu kontrolki ScriptManager można wykonać wywołanie usługi sieci Web, a zwrócone dane można obsłużyć za pomocą funkcji wywołania zwrotnego. Usługa sieci Web jest wywoływana przez odwoływanie się do jej przestrzeni nazw (jeśli istnieje), nazwy klasy i nazwy metody sieci Web. Wszystkie parametry przekazywane do usługi sieci Web można zdefiniować wraz z funkcją wywołania zwrotnego, która obsługuje zwracane dane.
Przykład użycia serwera proxy języka JavaScript do wywołania metody internetowej o nazwie GetCustomersByCountry() jest wyświetlany na liście 13. Funkcja GetCustomersByCountry() jest wywoływana, gdy użytkownik końcowy kliknie przycisk na stronie.
Lista 13. Wywoływanie usługi internetowej przy użyciu serwera proxy języka JavaScript.
function GetCustomerByCountry()
{
var country = $get("txtCountry").value;
InterfaceTraining.CustomersService.GetCustomersByCountry(country, OnWSRequestComplete);
}
function OnWSRequestComplete(results)
{
if (results != null)
{
CreateCustomersTable(results);
GetMap(results);
}
}
To wywołanie odwołuje się do przestrzeni nazw InterfaceTraining, klasy CustomersService i metody sieci Web GetCustomersByCountry zdefiniowanej w usłudze. Przekazuje wartość kraju uzyskaną z pola tekstowego, a także funkcję wywołania zwrotnego o nazwie OnWSRequestComplete, która powinna być wywoływana, gdy zostanie zwrócone wywołanie asynchronicznej usługi sieci Web. OnWSRequestComplete obsługuje tablicę obiektów Klienta zwracanych z usługi i konwertuje je na tabelę wyświetlaną na stronie. Dane wyjściowe wygenerowane na podstawie wywołania są wyświetlane na rysunku 1.
Rysunek 1. Powiązanie danych uzyskanych przez asynchroniczne wywołanie AJAX do usługi sieci Web. (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Serwery proxy języka JavaScript mogą również wykonywać wywołania jednokierunkowe do usług sieci Web w przypadkach, gdy metoda sieci Web powinna być wywoływana, ale serwer proxy nie powinien czekać na odpowiedź. Na przykład możesz wywołać usługę sieci Web, aby uruchomić proces, taki jak przepływ pracy, ale nie czekać na wartość zwracaną z usługi. W przypadkach, gdy jednokierunkowe wywołanie musi zostać wykonane do usługi, funkcja wywołania zwrotnego pokazana w liście 13 można po prostu pominąć. Ponieważ nie zdefiniowano funkcji wywołania zwrotnego, obiekt proxy nie będzie czekać na zwrócenie danych przez usługę sieci Web.
Obsługa błędów
Asynchroniczne wywołania zwrotne do usług sieci Web mogą napotkać różne typy błędów, takich jak awaria sieci, niedostępność usługi sieci Web lub zwracany wyjątek. Na szczęście obiekty serwera proxy języka JavaScript generowane przez narzędzie ScriptManager umożliwiają zdefiniowanie wielu wywołań zwrotnych w celu obsługi błędów i niepowodzeń oprócz pokazanego wcześniej wywołania zwrotnego powodzenia. Funkcję wywołania zwrotnego błędu można zdefiniować bezpośrednio po standardowej funkcji wywołania zwrotnego w wywołaniu metody sieci Web, jak pokazano na liście 14.
Lista 14. Definiowanie funkcji wywołania zwrotnego błędów i wyświetlanie błędów.
function GetCustomersByCountry()
{
var country = $get("txtCountry").value;
InterfaceTraining.CustomersService.GetCustomersByCountry(country,
OnWSRequestComplete, OnWSRequestFailed);
}
function OnWSRequestFailed(error)
{
alert("Stack Trace: " + error.get_stackTrace() + "/r/n" +
"Error: " + error.get_message() + "/r/n" +
"Status Code: " + error.get_statusCode() + "/r/n" +
"Exception Type: " + error.get_exceptionType() + "/r/n" +
"Timed Out: " + error.get_timedOut());
}
Wszelkie błędy występujące po wywołaniu usługi internetowej wyzwalają funkcję wywołania zwrotnego OnWSRequestFailed(), która akceptuje obiekt reprezentujący błąd jako parametr. Obiekt błędu uwidacznia kilka różnych funkcji w celu określenia przyczyny błędu, a także tego, czy upłynął limit czasu wywołania. Na liście 14 przedstawiono przykład użycia różnych funkcji błędów, a rysunek 2 przedstawia przykład danych wyjściowych wygenerowanych przez funkcje.
Rysunek 2. Dane wyjściowe wygenerowane przez wywołanie funkcji błędów AJAX ASP.NET. (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Obsługa danych XML zwracanych z usługi internetowej
Wcześniej pokazano, jak metoda sieci Web może zwracać nieprzetworzone dane XML przy użyciu atrybutu ScriptMethod wraz z właściwością ResponseFormat. Gdy element ResponseFormat jest ustawiony na ResponseFormat.Xml, dane zwrócone z usługi sieci Web są serializowane jako XML, a nie JSON. Może to być przydatne, gdy dane XML muszą być przekazywane bezpośrednio do klienta do przetwarzania przy użyciu języka JavaScript lub XSLT. Obecnie program Internet Explorer 5 lub nowszy zapewnia najlepszy model obiektów po stronie klienta na potrzeby analizowania i filtrowania danych XML ze względu na wbudowaną obsługę programu MSXML.
Pobieranie danych XML z usługi sieci Web nie różni się od pobierania innych typów danych. Zacznij od wywołania serwera proxy języka JavaScript w celu wywołania odpowiedniej funkcji i zdefiniowania funkcji wywołania zwrotnego. Gdy wywołanie zwróci, możesz przetworzyć dane w funkcji wywołania zwrotnego.
Na liście 15 przedstawiono przykład wywoływania metody sieci Web o nazwie GetRssFeed(), która zwraca obiekt XmlElement. GetRssFeed() akceptuje pojedynczy parametr reprezentujący adres URL źródła danych RSS do pobrania.
Lista 15. Praca z danymi XML zwracanymi z usługi sieci Web.
function GetRss()
{
InterfaceTraining.DemoService.GetRssFeed(
"https://blogs.interfacett.com/dan-wahlins-blog/rss.xml",
OnWSRequestComplete);
}
function OnWSRequestComplete(result)
{
if (document.all) //Filter for IE DOM since other browsers are limited
{
var items = result.selectNodes("//item");
for (var i=0;i<items.length;i++)
{
var title = items[i].selectSingleNode("title").text;
var href = items[i].selectSingleNode("link").text;
$get("divOutput").innerHTML +=
"<a href='" + href + "'>" + title + "</a><br/>";
}
}
else
{
$get("divOutput").innerHTML = "RSS only available in IE5+";
}
}
Ten przykład przekazuje adres URL do źródła danych RSS i przetwarza zwrócone dane XML w funkcji OnWSRequestComplete(). OnWSRequestComplete() najpierw sprawdza, czy przeglądarka jest internet Explorer, aby sprawdzić, czy analizator MSXML jest dostępny. Jeśli tak jest, instrukcja XPath jest używana do lokalizowania wszystkich <tagów elementów> w kanale informacyjnym RSS. Każdy element jest następnie iterowany, a skojarzone <tagi tytułu> i <linku> znajdują się i przetwarzane w celu wyświetlenia danych każdego elementu. Rysunek 3 przedstawia przykład danych wyjściowych wygenerowanych na podstawie wykonywania wywołania ASP.NET AJAX za pośrednictwem serwera proxy języka JavaScript do metody internetowej GetRssFeed().
Obsługa typów złożonych
Typy złożone akceptowane lub zwracane przez usługę internetową są automatycznie udostępniane za pośrednictwem serwera proxy języka JavaScript. Jednak zagnieżdżone typy złożone nie są bezpośrednio dostępne po stronie klienta, chyba że atrybut GenerateScriptType zostanie zastosowany do usługi zgodnie z wcześniejszym opisem. Dlaczego chcesz użyć zagnieżdżonego typu złożonego po stronie klienta?
Aby odpowiedzieć na to pytanie, załóżmy, że strona ASP.NET AJAX wyświetla dane klientów i umożliwia użytkownikom końcowym aktualizowanie adresu klienta. Jeśli usługa sieci Web określa, że typ adresu (typ złożony zdefiniowany w klasie CustomerDetails) można wysłać do klienta, proces aktualizacji można podzielić na oddzielne funkcje w celu lepszego ponownego użycia kodu.
Rysunek 3. Dane wyjściowe tworzone na podstawie wywołania usługi sieci Web zwracającej dane RSS. (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Na liście 16 przedstawiono przykład kodu po stronie klienta, który wywołuje obiekt Address zdefiniowany w przestrzeni nazw modelu, wypełnia je zaktualizowanymi danymi i przypisuje go do właściwości Address obiektu CustomerDetails. Obiekt CustomerDetails jest następnie przekazywany do usługi sieci Web w celu przetworzenia.
Lista 16. Używanie zagnieżdżonych typów złożonych
function UpdateAddress()
{
var cust = new Model.CustomerDetails();
cust.CustomerID = $get("hidCustomerID").value;
cust.Address = CreateAddress();
InterfaceTraining.DemoService.UpdateAddress(cust,OnWSUpdateComplete);
}
function CreateAddress()
{
var addr = new Model.Address();
addr.Street = $get("txtStreet").value;
addr.City = $get("txtCity").value;
addr.State = $get("txtState").value;
return addr;
}
function OnWSUpdateComplete(result)
{
alert("Update " + ((result)?"succeeded":"failed")+ "!");
}
Tworzenie i używanie metod strony
Usługi internetowe zapewniają doskonały sposób uwidaczniania usług, które można ponownie używać dla różnych klientów, w tym ASP.NET stron AJAX. Mogą jednak wystąpić przypadki, w których strona musi pobrać dane, które nigdy nie będą używane ani udostępniane przez inne strony. W takim przypadku utworzenie pliku asmx w celu umożliwienia stronie dostępu do danych może wydawać się nadmierne, ponieważ usługa jest używana tylko przez jedną stronę.
ASP.NET AJAX udostępnia inny mechanizm tworzenia wywołań przypominających usługę internetową bez tworzenia autonomicznych plików asmx. Odbywa się to przy użyciu techniki określanej jako "metody strony". Metody stron są statyczne (współużytkowane w VB.NET) metody osadzone bezpośrednio na stronie lub pliku obok kodu, które mają zastosowany atrybut WebMethod. Stosując atrybut WebMethod, można je wywołać przy użyciu specjalnego obiektu JavaScript o nazwie PageMethods, który jest dynamicznie tworzony w czasie wykonywania. Obiekt PageMethods działa jako serwer proxy, który chroni cię przed procesem serializacji/deserializacji JSON. Należy pamiętać, że aby można było użyć obiektu PageMethods, należy ustawić właściwość EnablePageMethods właściwości ScriptManager na true.
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
</asp:ScriptManager>
Na liście 17 przedstawiono przykład definiowania dwóch metod strony w ASP.NET klasie kod-obok. Te metody pobierają dane z klasy warstwy biznesowej znajdującej się w folderze App_Code witryny sieci Web.
Lista 17. Definiowanie metod stron.
[WebMethod]
public static Customer[] GetCustomersByCountry(string country)
{
return Biz.BAL.GetCustomersByCountry(country);
}
[WebMethod]
public static Customer[] GetCustomersByID(string id)
{
return Biz.BAL.GetCustomersByID(id);
}
Gdy scriptManager wykryje obecność metod sieci Web na stronie, generuje dynamiczne odwołanie do obiektu PageMethods wymienionego wcześniej. Wywoływanie metody sieci Web odbywa się przez odwoływanie się do klasy PageMethods, po której następuje nazwa metody i wszelkie niezbędne dane parametrów, które powinny zostać przekazane. Na liście 18 przedstawiono przykłady wywoływania dwóch pokazanych wcześniej metod strony.
Lista 18. Wywoływanie metod strony za pomocą obiektu JavaScript PageMethods.
function GetCustomerByCountry()
{
var country = $get("txtCountry").value;
PageMethods.GetCustomersByCountry(country, OnWSRequestComplete);
}
function GetCustomerByID()
{
var custID = $get("txtCustomerID").value;
PageMethods.GetCustomersByID(custID, OnWSRequestComplete);
}
function OnWSRequestComplete(results)
{
var searchResults = $get("searchResults");
searchResults.control.set_data(results);
if (results != null) GetMap(results[0].Country,results);
}
Użycie obiektu PageMethods jest bardzo podobne do obiektu serwera proxy języka JavaScript. Najpierw należy określić wszystkie dane parametrów, które powinny zostać przekazane do metody page, a następnie zdefiniować funkcję wywołania zwrotnego, która powinna być wywoływana, gdy zostanie zwrócone wywołanie asynchroniczne. Można również określić wywołanie zwrotne błędów (zapoznaj się z listą 14, aby zapoznać się z przykładem błędów obsługi).
AutouzupełnianieExtender i zestaw narzędzi ASP.NET AJAX
Zestaw narzędzi ASP.NET AJAX (dostępny w witrynie https://github.com/DevExpress/AjaxControlToolkit) oferuje kilka kontrolek, których można użyć do uzyskiwania dostępu do usług sieci Web. W szczególności zestaw narzędzi zawiera przydatną kontrolkę o nazwie AutoCompleteExtender
, która może służyć do wywoływania usług sieci Web i wyświetlania danych na stronach bez konieczności pisania kodu JavaScript w ogóle.
Kontrolka AutouzupełnianieExtender może służyć do rozszerzania istniejących funkcji pola tekstowego i ułatwiania użytkownikom lokalizowania szukanych danych. Podczas wpisywania w polu tekstowym kontrolka może służyć do wykonywania zapytań względem usługi internetowej i pokazuje wyniki poniżej pola tekstowego dynamicznie. Rysunek 4 przedstawia przykład użycia kontrolki AutoCompleteExtender do wyświetlania identyfikatorów klientów dla aplikacji pomocy technicznej. Ponieważ użytkownik wpisze różne znaki w polu tekstowym, różne elementy będą wyświetlane poniżej na podstawie ich danych wejściowych. Użytkownicy mogą następnie wybrać żądany identyfikator klienta.
Użycie autouzupełnianiaExtender na stronie ASP.NET AJAX wymaga dodania zestawu AjaxControlToolkit.dll do folderu bin witryny sieci Web. Po dodaniu zestawu zestawu narzędzi należy odwołać się do niego w pliku web.config, aby kontrolki, które zawiera, były dostępne dla wszystkich stron w aplikacji. Można to zrobić, dodając następujący tag w tagu <kontrolek> web.config:
<add namespace="AjaxControlToolkit" assembly="AjaxControlToolkit" tagPrefix="ajaxToolkit"/>
W przypadkach, w których wystarczy użyć kontrolki na określonej stronie, możesz odwoływać się do niej, dodając dyrektywę Reference do górnej części strony, jak pokazano dalej, zamiast aktualizować plik web.config:
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit"
TagPrefix="ajaxToolkit" %>
Rysunek 4. Używanie kontrolki AutoCompleteExtender. (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Po skonfigurowaniu witryny internetowej do korzystania z zestawu narzędzi AJAX ASP.NET można dodać kontrolkę AutouzupełnianieExtender na stronie, podobnie jak w przypadku zwykłego sterowania serwerem ASP.NET. Na liście 19 przedstawiono przykład użycia kontrolki do wywołania usługi sieci Web.
Lista 19. Za pomocą kontrolki autouzupełniania zestawu narzędzi AJAX ASP.NET.
<ajaxToolkit:AutoCompleteExtender ID="extTxtCustomerID" runat="server"
MinimumPrefixLength="1" ServiceMethod="GetCustomerIDs"
ServicePath="~/CustomersService.asmx"
TargetControlID="txtCustomerID" />
AutouzupełnianieExtender ma kilka różnych właściwości, w tym identyfikator standardowy i właściwości runat znalezione na kontrolkach serwera. Oprócz tych, umożliwia zdefiniowanie liczby znaków, które użytkownik końcowy wpisze przed wykonaniem zapytania dotyczącego danych przez usługę internetową. Właściwość MinimumPrefixLength wyświetlana na liście 19 powoduje, że usługa jest wywoływana za każdym razem, gdy znak jest wpisywany w polu tekstowym. Należy zachować ostrożność ustawiając tę wartość, ponieważ za każdym razem, gdy użytkownik wpisze znak, usługa sieci Web zostanie wywołana w celu wyszukania wartości pasujących do znaków w polu tekstowym. Usługa sieci Web do wywołania oraz docelowa metoda sieci Web są definiowane odpowiednio przy użyciu właściwości ServicePath i ServiceMethod. Na koniec właściwość TargetControlID identyfikuje pole tekstowe, do którego ma być podłączana kontrolka AutoCompleteExtender.
Wywoływana usługa sieci Web musi mieć zastosowany atrybut ScriptService zgodnie z wcześniejszym opisem, a docelowa metoda sieci Web musi akceptować dwa parametry o nazwie prefiksText i count. Parametr prefixText reprezentuje znaki wpisane przez użytkownika końcowego, a parametr count reprezentuje liczbę zwracanych elementów (wartość domyślna to 10). Na liście 20 przedstawiono przykład metody sieci Web GetCustomerIDs wywoływanej przez kontrolkę AutoCompleteExtender pokazaną wcześniej na liście 19. Metoda sieci Web wywołuje metodę warstwy biznesowej, która z kolei wywołuje metodę warstwy danych, która obsługuje filtrowanie danych i zwraca pasujące wyniki. Kod metody warstwy danych jest wyświetlany na liście 21.
Lista 20. Filtrowanie danych wysyłanych z kontrolki AutoCompleteExtender.
[WebMethod]
public string[] GetCustomerIDs(string prefixText, int count)
{
return Biz.BAL.GetCustomerIDs(prefixText, count);
}
Lista 21. Filtrowanie wyników na podstawie danych wejściowych użytkownika końcowego.
public static string[] GetCustomerIDs(string prefixText, int count)
{
//Customer IDs cached in _CustomerIDs field to improve performance
if (_CustomerIDs == null)
{
List<string> ids = new List<string>();
//SQL text used for simplicity...recommend using sprocs
string sql = "SELECT CustomerID FROM Customers";
DbConnection conn = GetDBConnection();
conn.Open();
DbCommand cmd = conn.CreateCommand();
cmd.CommandText = sql;
DbDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
ids.Add(reader["CustomerID"].ToString());
}
reader.Close();
conn.Close();
_CustomerIDs = ids.ToArray();
}
int index = Array.BinarySearch(_CustomerIDs, prefixText, new CaseInsensitiveComparer());
//~ is bitwise complement (reverse each bit)
if (index < 0) index = ~index;
int matchingCount;
for (matchingCount = 0; matchingCount < count && index + matchingCount < _CustomerIDs.Length; matchingCount++)
{
if (!_CustomerIDs[index + matchingCount].StartsWith(prefixText, StringComparison.CurrentCultureIgnoreCase))
{
break;
}
}
String[] returnValue = new string[matchingCount];
if (matchingCount > 0)
{
Array.Copy(_CustomerIDs, index, returnValue, 0, matchingCount);
}
return returnValue;
}
Podsumowanie
ASP.NET AJAX zapewnia doskonałą obsługę wywoływania usług internetowych bez konieczności pisania wielu niestandardowych kodu JavaScript do obsługi komunikatów żądania i odpowiedzi. W tym artykule przedstawiono sposób włączania usług sieci Web .NET AJAX w celu umożliwienia im przetwarzania komunikatów JSON i sposobu definiowania serwerów proxy języka JavaScript przy użyciu kontrolki ScriptManager. Pokazano również, jak można używać serwerów proxy języka JavaScript do wywoływania usług sieci Web, obsługiwania prostych i złożonych typów oraz radzenia sobie z błędami. Na koniec pokazano, jak można użyć metod stron w celu uproszczenia procesu tworzenia i wykonywania wywołań usługi internetowej oraz sposobu, w jaki kontrolka AutoCompleteExtender może pomóc użytkownikom końcowym podczas wpisywania. Mimo że updatePanel dostępny w ASP.NET AJAX z pewnością będzie kontrolą wyboru dla wielu programistów AJAX ze względu na prostotę, wiedząc, jak wywoływać usługi internetowe za pośrednictwem serwerów proxy JavaScript może być przydatne w wielu aplikacjach.
Życiorys
Dan Wahlin (Microsoft Most Valuable Professional for ASP.NET and XML Web Services) to instruktor programowania i konsultant architektury platformy .NET w interface technical training (http://www.interfacett.com). Dan założył XML dla witryny internetowej ASP.NET Developers (www.XMLforASP.NET), jest w Biurze Prelegenta INETA i przemawia na kilku konferencjach. Dan współautor professional Windows DNA (Wrox), ASP.NET: Tips, Tutorials and Code (Sams), ASP.NET 1.1 Insider Solutions, Professional ASP.NET 2.0 AJAX (Wrox), ASP.NET 2.0 MVP Hacks i autorem XML dla deweloperów ASP.NET (Sams). Kiedy nie pisze kodu, artykułów ani książek, Dan lubi pisać i nagrywać muzykę i grać w golfa i koszykówkę z żoną i dziećmi.
Scott Cate współpracuje z technologiami internetowymi firmy Microsoft od 1997 roku i jest prezesem myKB.com (www.myKB.com), gdzie specjalizuje się w pisaniu ASP.NET opartych na aplikacjach skoncentrowanych na rozwiązaniach oprogramowania bazy wiedzy. Scott może skontaktować się za pośrednictwem poczty e-mail lub scott.cate@myKB.com jego bloga na ScottCate.com