Artykuł pochodzi w serii przygotowań do egzaminu 70-562 ASP.NET.
ASP.NET udostępnia prosty model dla klienta używającego Web Services. Generowany jest obiekt proxy kiedy wykorzystujemy referencje do Web Services. Obiekt proxy zajmuje się serializacją, wiadomościami SOAP i związanymi z nimi procesami. Poniżej rysunek z TK modelu XML Web Service w ASP.NET :

Tworzenie Web Service w ASP.NET
Tworząc XML Web Services w ASP.NET dziedziczymy po klasie System.Web.Services.WebService. Klasa ta zapewnia wrapper dla kodu usługi. Spójrzmy na schemat relacji klas przy tworzeniu Web Service:

Każda z tych klas kontroluje prace naszej usługi webowej. Jak widzimy aby uzyskać dostęp do standardowych funkcji ASP.NET musimy podziedziczyć po klasie WebService. Atrybuty klasa pozwalają oznaczyć część naszego kodu który jest związany z XML Web Service. Elementy oznaczone jako te przeznaczone do stosowania przez usługę są identyfikowane automatycznie przez ASP.NET. Również klasa ta “umie” deserializować wnioski, wywoływać usługę czy też serializować odpowiedzi. Obsługuje również prace z SOAP, XML, Web Services Description Language (WSDL) i związanych z nimi standardów usług internetowych.
Projekt Usługi Web ASP.NET
Web Service definiujemy w pliku .asmx. Plik ten może być dodawany bezpośrednio do istniejącej witryny sieci Web. Jest to przydatne kiedy nasze witryna oprócz bycia samą w sobie stroną www będzie potrzebowała korzystać z usług. Oczywiście możemy stworzyć stronę www która składa się z samych usług.
Tak jak strony www, web service jest wyrażony przy pomocy URL. Co w praktyce oznacza adres w stylu http://mojadomena/mojausluga.asmx. W samym pliku .asmx jest tylko informacja, że kod obsługujący stronę znajduje się w oddzielnym pliku. Załóżmy, że chcemy dodać usługę w której mamy metody, udostępniające nam prace z Autorami na jakiejś przykładowej bazie danych. Możemy zacząć od stworzenia pliku Authors.asmx. W pliku tym zawieramy dyrektywę @ WebService która wskazuje rzeczywiste miejsce kodu usługi. W kodzie wygląda to dokładnie tak:
1: //C#
2: <%@ WebService Language="C#" CodeBehind="Authors.asmx.cs" Class="PubsServices.Authors"
3: %>
Klasa WebServiceAttribute
Stworzenie pliku .asmx plus udostępnienie publicznej metody oznaczonej jako [WebMethod] (o czym za chwile) jest wystarczające do określenia usługi w środowisku ASP.NET. Istnieje jednak wiele innych klas które mogą zapewnić dodatkową funkcjonalność. Jedną z nich jest tytułowa WebServiceAttribute. Może ona być wykorzystana do dostarczenia informacji o usłudze sieci Web. Informacje te są wykorzystywane po stronie klienckiej, podczas odwołania się do usługi.
Możemy podawać zarówno przestrzeń nazw i opis naszej usługi sieciowej przez stosowanie atrybutu WebService do naszej klasy. Przestrzeń nazw określona dla naszej usługi, natomiast opisem jest zwykły tekst. Visual Studio do czasu określenia właściwej domeny używa tempuri.org .Przykład dodawania takiego atrybutu dla klasy Authors poniżej:
1: //C#
2: [WebService(Description = "Services related to published authors",
3: Namespace = "http://tempuri.org/")]
4: public class Authors
Klasa WebService
Klasa WebService może stanowić klasę bazową do stworzenia XML Web Services w ASP.NET. Klasa ta jest podobna do klasy Page w stronach www. Umożliwia ona dostęp do takich obiektów jak Application czy Session. Na początku podkreśliłem, że klasa WebService może stanowić klasę bazową…może ale nie musi ;) Tak naprawdę powinniśmy po niej dziedziczyć wtedy kiedy jest nam potrzebna funkcjonalność aplikacji ASP.NET. Poniżej kod który pokazuje zapis klasy z dziedziczeniem:
1: //C#
2: [WebService(Description = "Services related to published authors",
3: Namespace = "http://tempuri.org/")]
4: public class Authors : System.Web.Services.WebService
Klasa WebMethodAttribute
Nasza usługa udostępnia metody a każda z tych metod stanowi pewną obudowaną funkcjonalność. W klasie metody te oznaczamy atrybutem [WebMethod]. Spowoduje to, że daną metodę chcemy “udostępnić światu”. Można przypisać atrybut [WebMethod] bez żadnych dodatkowych parametrów i to po prostu nam określi metodę jako metodę usługi sieci Web. Jednak mamy szereg dostępnych parametrów które potrafią dodać pewną funkcjonalność. Na przykład enableSessionState (określa czy metoda ma w jakiś sposób współpracować z session state, do wyboru true/false) czy bufferResponse (określa czy odpowiedź ma być buforowana z powrotem do klienta). Poniżej jest kod który wykorzystuje parametr cacheDuration (określa ile czasu mają być przechowywane dane w pamięci podręcznej) :
1: //C#
2: [WebMethod(CacheDuration=300)]
3: public DataTable GetAuthorTitles(string authorId)
4: { ... }
Używanie Web Service w ASP.NET
Usługę Webową możemy uruchomić praktycznie w każdej aplikacji która jest w stanie stworzyć połączenie HTTP. Nawet w aplikacji konsolowej ;) Aby rozpocząć korzystanie z usługi, takowa musi już gdzieś istnieć. Może ona istnieć gdzieś na serwerze, w naszym projekcie, gdziekolwiek. W projekcie który mam wybieramy w solution explorer PPM na projekt i wybieramy Add Web Reference. Otworzy się nam okno gdzie ustawiamy m.in adres URL, wybieramy pliki typu .asmx i ustawiamy nazwę dla naszej referencji. Poniżej zrzut ekranu okna w którym jest pokazane przykładowe dodanie usługi Authors.asmx :
Widzimy albo i nie ;) , że usługa ta udostępnia nam dwie metody GetAuthor(); i GetAuthorTitles(); Co one miały robić w domyśle autora nie ważne ;)
Wywoływanie Web Service
Jest to tak proste, jak pisanie kodu w celu wywołania metody. Na przykład, następujący kod pokazuje jak wywołać metodę GetAuthor() :
1: //C#
2: PubServices.Authors pubs = new PubServices.Authors();
3: PubServices.Author auth = pubs.GetAuthor();
4: Label1.Text = auth.FirstName + " " + auth.LastName;
Można również wiązać wywołania usługi. Jako przykład użyjemy wcześniej wspomnianej metody GetAuthorsTitles() która zwracała DataTable dlatego aby powiązać dane np. z GridView wystarczy odpowiednio go zdefiniować:
1: <asp:ObjectDataSource runat="server"
2: ID="ObjectDataSourceAuthors"
3: TypeName="PubsServices.Authors">
4: SelectMethod="GetAuthorTitles"
5: <SelectParameters>
6: <asp:QueryStringParameter
7: Name="authorId"
8: QueryStringField="auId"
9: Type="String" />
10: </SelectParameters>
11: </asp:ObjectDataSource>
12: <asp:GridView ID="GridView1" runat="server"
13: DataSourceID="ObjectDataSourceAuthors">
14: </asp:GridView>
Łączenie się z usługa przy pomocy skryptów z wykorzystaniem AJAX
Możemy użyć wbudowany w ASP.NET AJAX funkcjonalności aby wywołać usługę webową przy użyciu javascript po stronie klienta. Jednak trzeba pamiętać o pewnych rzeczach przy konfiguracji takowego rozwiązania. Ważne jest np. aby nasza “strona kliencka” była w tej samej domenie co pliki .asmx! Poniższe kroki powinny pomóc nam przy konfiguracji:
- oznacz metody których będziesz chciał w taki sposób używać parametrem ScriptServiceAttribute.
- “zarejestruj” na stronie ScriptHandlerFactory. Możesz to zrobić wewnątrz elementu <system.web> <httpHandlers> w pliku Web.config.
- dodaj ScirptManager do naszej strony. Jest on wymagany dla każdych stron używających AJAX, tutaj dodatkowo wewnątrz jego trzeba dodać referencje do usług (ServiceReference).
- dodaj metody javascript do strony.
- można również dodać inne metody javascript którę obsłużą callback
Dla większego zobrazowania przykład- otóż wyobraź sobie, że masz usługę która pobiera temperaturę w stopniach Farenheita a zwraca w Celsjuszach. Kod takiej metody w usłudze wyglądałby następująco:
1: //C#
2: [System.Web.Script.Services.ScriptService]
3: [WebService(Namespace = "http://tempuri.org/")]
4: public class TempConversion : System.Web.Services.WebService
5: {
6: [WebMethod]
7: public float GetCelsius(float temperature)
8: {
9: return (5 / 9) * (temperature - 32);
10: }
11: }
Następnie musimy się upewnić, że jest dodany w web.configu ScriptHandlerFactory. Oto kod:
1: <httpHandlers>
2: <remove verb="*" path="*.asmx" />
3: <add verb="*" path="*.asmx" validate="false"
4: type="System.Web.Script.Services.ScriptHandlerFactory" />
5: </httpHandlers>
Pozostaje nam stworzyć stronę po stronie klienckiej. Pamiętajmy o dodaniu ScriptManagera i dodaniu do niego referencji:
1: <asp:ScriptManager runat="server" ID="ScriptManager1">
2: <Services>
3: <asp:ServiceReference
4: path="TempConversion.asmx" />
5: </Services>
6: </asp:ScriptManager>
Następnym krokiem jest dodanie metod javascript:
1: <script type="text/javascript">
2: function GetCelsius()
3: {
4: var val = document.getElementById("TextBoxTemp");
5: TempConversion.GetCelsius(val.value, FinishCallback);
6: }
7: function FinishCallback(result)
8: {
9: var results = document.getElementById("LabelResults");
10: results.innerHTML = result;
11: }
12: </script>
I na końcu oczywiście pola tekstowe do wpisywania wartości i wyniku oraz przycisk wywołujący metodę:
1: <asp:TextBox ID="TextBoxTemp" runat="server"></asp:TextBox>
2: <asp:Label ID="LabelResults" runat="server" Text=""></asp:Label>
3: <br />
4: <input id="Button1" type="button" value="Calculate" onclick="GetCelsius()" />
To tyle w tym temacie. Traning Kit porusza również ważny temat zabezpieczenia naszej usługi. Ale to pozostawiam Wam jako prace domową na weekend. Moment na doczytanie ;) Do poniedziałku! :)