BETA
Aby się zalogować, najpiew wybierz portal.
Aby się zarejestrować, najpiew wybierz portal.
Podaj słowa kluczowe
Słowa kluczowe muszą mieć co najmniej 3 sąsiadujące znaki alfanumeryczne
Pole zawiera niedozwolone znaki

Baza wiedzy











Wstęp do technologii WCF

28-06-2007 23:34 | Farol
Ten artykuł ma za zadanie przedstawić technologię WCF, prezentując jej architekturę oraz wady i zalety. Zakładana jest podstawowa wiedza z zakresu programowanie aplikacji w technologii .NET 2.0 i znajomość Visual Studio 2005.

Co to jest WCF?

 

WCF (Windows Communication Foundation nazwa kodowa: Indigo) jest to jeden z 4 filarów .NET 3.0 (wcześniej znanego, jako WinFX). Jest to technologia stworzona, aby wspomóc programowanie aplikacji rozproszonych oraz ułatwić implementację systemów zaprojektowanych w architekturze SOA. WCF jest niejako połączeniem wszystkich innych technologii Microsoftu do tworzenia aplikacji rozproszonych i komunikacji:  .NET Remoting, MSMQ, COM+ (EnterpriseServices), WebServices. Integruje te technologie, czerpie z nich to, co najlepsze i dodaje wiele innych zalet. Kolejnym bardzo ważną zaletą jest fakt, że WCF wprowadza ujednolicony model obiektowy dla wszystkich powyższych technologii. WCF umożliwia zarówno komunikację 2 procesów na jednym komputerze jak i komunikację przez sieć LAN oraz przez Internet. Co więcej tworząc serwis w WCF’ie w żaden sposób nie przejmujemy się rzeczami związanymi z komunikacją jak: protokołami transportującymi, szyfrowaniem itp., ponieważ te wszystkie elementy są ustalane w pliku konfiguracyjnym i w żaden sposób nie wpływają na implementację serwisu. WCF jest technologią, w której dużo można uzyskać programując deklaratywnie poprzez wykorzystanie atrybutów oraz wpisy w plikach konfiguracyjnych.

Architektura Windows Communication Foundation

                                                        

WCF jest technologią wielowarstwową, co sprawia, że rozwiązanie tworzone w tej technologii są bardzo elastyczne i łatwe w konfiguracji. Poniżej przedstawiam rysunek prezentujący architekturę WCF’a, a pod nim pobieżny opis poszczególnych części.

 

WCF Architektura.jpg

 

 

Contracts

Część Contracts definiuje informacje związane z przesyłanymi wiadomościami (ang. message). Dla przykładu, wszystkie parametry przyjmowane oraz wysyłane przez serwis są określone przez DataContract. ServiceContract służy do określenia sygnatur metod, jakie mogą być wywoływane przez klientów danego serwisu. Przy pomocy MessageContract mamy wpływ na wygląd poszczególnych części wiadomości SOAP przesyłanych do i z serwisu. Policy and Binding opisuje zasady bezpieczeństwa związane z używanie serwisu WCF, określa protokół transportowy wiadomości oraz sposób ich szyfrowania.

ServiceRuntime

ServiceRuntime określa pewne zachowania (ang. Runtime Behaviors), które występują podczas wywoływania funkcjonalności serwisu. Dla przykładu określa ile wiadomości ma być przetwarzanych (ThrottlingBehavior) lub ile ma być instancji serwisu (InstanceBehavior). EceptionBehavior określa, jakie i ile informacji ma być przesłanych do klienta w przypadku wystąpienia wyjątku.

Messaging

Warstwa ta określa szczegóły związane ze sposobem przesyłania wiadomości składa się z kanałów (ang. channel), które przetwarzają wiadomości.

Rozróżniamy dwa typy kanałów: kanały transportujące (ang. Transport channel) oraz  kanały protokołów (ang. Protocol channel).

Kanały transportujące zapisują i odczytują wiadomości z sieci (lub innego medium transmisji np. TCP, MSMQ, nazwane potoki, HTTP).

Kanał protokołów zapewnia protokoły przetwarzania wiadomości poprzez odczyt i zapis dodatkowych nagłówków wiadomości. Przykładami takich protokołów mogą być WS-Security i WS-Reliability (protokoły implementujące standardy bezpieczeństwa oraz niezawodności dedykowane dla technologii WebService).

Hosting and Activation

Po napisaniu rozwiązania w WCF trzeba go jeszcze gdzieś hostować i w tym momencie ta warstwa technologii WCF pokazuje swoje możliwości. Ponieważ poza możliwością hostowania serwisów na serwerze ISS mamy kilka innych możliwości. Możemy, hostować aplikacje WCF ręcznie w plikach wykonywalnych (.EXE), jako usługi systemu Windows (Windows Services) lub przez niezależne aplikacje takie jak WAS (Windows Activation Service). Również możemy hostować komponenty COM+ jako aplikacje WCF’owe.

 

Service

W technologii WCF tworzymy serwisy (ang. service), czyli aplikacje, które mają za zadanie odbierać zapytania od klientów i je realizować. Taki serwis to nic innego jak hostowana aplikacja napisana, w WCF, która ma zdefiniowane sposób komunikacji z klientem (interfejsy), protokoły wykorzystywane do komunikacji, pewne dodatkowe właściwości jak bezpieczeństwo, szyfrowanie. Z pojęciem serwisu bezpośrednio jest związanych kilka pojęć, do których teraz przejdziemy.

Endpoint

Każdy serwis może mieć dowolnie wiele endpoint’ów, a każdy z nich jest swoistego rodzaju sposobem na komunikację z serwisem. Kążdy endpoint może oferować inne funkcjonalności oraz różnić się protokołami, dzięki którym można się komunikować z serwisem. Tak, więc każdy serwis może mieć kilka endpoint’ów aby np. wspierać równocześnie połączenia poprzez HTML/SOAP jak i poprzez TCP. Teraz zagłębmy się w tzw. ABC endpoint’a.

ABC – Adress, Binding, Contract

 

ServiceEndpoint

Address (gdzie?)

Adress określa adres danego endpoint’a składa się z:

a)      URI (Uniform Resource Identifier)

b)      Identity – określa tożsamość, jaka ma być używana w celu Autentykacji. W większości przypadków jest używane URI danego endpoint’a, jednak w niektórych sytuacjach możemy chcieć podać tożsamość niezależnie.

c)       AdressHeaders – opcjonalne nagłówki, w których są zawarte dodatkowe informacje do komunikacji z endpoint’em. Przykładowo dodatkowe nagłówki są używane w przypadku, gdy kilka endpoint’ów korzysta z tego samego URI.

Adres ten jest reprezentowany przez klasę EndpointAdress.

Binding (jak?)

Binding określa sposób, w jaki endpoint komunikuje się z klientami. Składa się na niego nazwa (name), przestrzeń nazw (ang. namespace) oraz kolekcja elementów bindujących. Nazwa i przestrzeń nazw jednoznacznie identyfikują endpoint w meta danych serwisu.

Każdy element Bindujący określają jedną właściwość określającą jak komunikować się z endpoint’em. Dla przykładu TCPBindingElement oznacz, że komunikacja przebiega przy wykorzystaniu protokołu TCP, natomiast SecurityBindingElement znaczy, że wykorzystywany jest model bezpieczeństwa związanego z SOAP.

Contract (co?)

Kontrakt (ang. Contract) określa operacje jakie wykonuje endpoint. Każda operacja jest wymianą wiadomości z określeniem czy jest to komunikacja w jedną stronę (ang. One-way) czy też na zasadzie pytanie/odpowiedź (ang. Request/reply).

Klasa ContractDescription służy do opisania kontraktu aplikacji WCF. Każda operacja wewnątrz kontraktu w klasie ContractDescription zawiera obiekt typu OperationDescription, który opisuje między innymi sposób komunikacji (jednostronna, pytanie/odpowiedź, duplex) oraz określa wiadomości przesyłane związane z tą operacją (informacje te są w MessageDescription). Obiekt klasy ContractDescription jest tworzony na podstawie interfejsu bądź klasy, która definiuje kontrakt poprzez model obiektowy WCF. Typ kontraktu jest oznaczony atrybutem ServiceContractAttribute a każda metoda, która ma być operacją endpoint’u jest oznaczona OperationContractAttribute.

Każdy kontrakt posiada również kolekcję obiektów typu ContractBehavior , które określają pewne zachowania związane z kontraktem.

ContractDescription

 

Behavior

 

Behavior są to klasy, które rozszerzają funkcjonalności aplikacji, WCF, np. security behavior nadzoruje autoryzację i impersonację.

Behavior bierze udział w tworzeniu kanałów (ang. channel) i może go modyfikować zgodnie z ustawieniami użytkownika.

Behavior odnoszący się do serwisu jest to typ implementujący IServiceBehavior natomiast behavior odnoszący się do kanału implementuje IChannelBehavior. O behavior będę pisał więcej w dalszych artykułach.

ServiceDescription i ChannelDescription

 

Klasa ServiceDescription jest strukturą opisującą serwis WCF i zawiera wszystkie wystawione endpoint’y, typ który implementuje serwis oraz Behavior przypisane do serwisu.

Obiekt typu ServiceDescription może być stworzony ręcznie lub też, (co częściej się zdarza) wygenerowany na podstawie typu z przypisanymi atrybutami. Kod do komunikacji z klientem może być również napisany samodzielnie lub wygenerowany na podstawie meta-danych przy pomocy narzędzia svcutil.exe.

ServiceDescription

ChannelDescription jest to klasa, która opisuje ze strony klienta połączenie z danym endpopint’em. Opis kanału zawiera behaviors, które opisują ten kanał oraz obiekt klasy ServiceEndpoint opisującą endpoint z jakim jest połączony klient.

ChannelDescription

WCF Runtime

 

Teraz będzie opisane kilka klas związanych już z uruchomieniem aplikacji WCF, odpowiedzialnych między innymi za formatowanie, szyfrowanie, odbieranie i wysyłanie wiadomości.

Message

W WCF podstawową jednostką przesyłaną między klientem a endpoint’em jest wiadomość (ang. message). Warto zaznaczyć, że format przesyłanych danych nie jest w żaden sposób określony, wszystko zależy od serializacji jaką użyjemy (binarna, XML itd.).

Channel

Kanały jak było napisane wcześniej służą do odbierania i wysyłania wiadomości. Wartym zaznaczenia jest fakt, że kanały mogą być budowane na podstawie innych kanałów rozszerzając ich możliwości.

EndpointListener

Po uruchomieniu aplikacji WCF obiektem, który reprezentuje działający endpoint jest właśnie EndpointListener. Obiekt tej klasy posiada adres nasłuchiwania, stos kanałów oraz filtrowanie i zarządzanie wiadomościami.

ServiceHost i ChannelFactory

Kluczową klasą dla wykonywania się WCF jest ServiceHost, ponieważ przy jej pomocy uruchamiamy wcześniej napisany serwis. To właśnie ServiceHost na podstawie kodu i plików konfiguracyjnych wypełnia kolekcję ServiceEndpoint w ServiceDescription. Następnie na podstawie ServiceDescription tworzy stos kanałów do obsługi wiadomości dla każdego endpoint’u.

Natomiast po stronie klienta główną rolę ma klasa ChannelFactory, która tworzy i wypełnia treścią obiektu związane z wywoływaniem serwisów WCF u klienta. ChannelFactory również tworzy stos kanałów na podstawie adresy endpoint’a, kontraktu i jego binding.

 

Przykład

 

Po tych kilku stronach teorii najwyższa pora, aby zobaczyć jak to działa w praktyce. Dla osób nowych dużo powyższych pojęć mogło być trochę trudne do ogarnięcia jednak teraz wszystko powinno się wyjaśnić.

Teraz stworzymy sobie prosty serwis i klienta, który będzie się z nim komunikował.

UWAGA!

Do tworzenia aplikacji WCF potrzebny jest: .NET 3.0 (system Win XP sp2, Win 2k3 sp1, Vista), Visual Studio „Orcas” lub VS 2005 z WCF Extensions, zalecane jest również zainstalowanie Windows Vista SDK co da nam dokumentację do WCF i zestaw przydatnych narzędzi do konfiguracji i nadzorowania aplikacji WCF.

Serwis

1.       Stwórzmy nowy projekt typu „WCF Service Library”

2.       Usuwamy plik Class1.cs aby nam nie przeszkadzałJ

3.       Teraz zabierzemy się za tworzenie ABC endpoint’u, zaczniemy od kontraktu, ponieważ to on definiuje udostępniane funkcjonalności. Jak było napisane wcześniej kontrakt możemy tworzyć na podstawie klasy bądź interfejsu. My stworzymy kontrakt na podstawie interfejsu co jest bardziej eleganckie.

Contract

a.       Dodajmy nowy plik do projektu, nazwijmy go IHelloWorldContract

b.      Następnie stwórzmy interfejs z dwoma metodami: string HelloWorld(), string HelloPerson(string name)

c.       Teraz oznaczmy interfejs jako kontrakt poprzez dodanie do niego atrybuty ServiceContract, a do metod OperationContract. Cały kod powinien wyglądać tak:

[Kod C#]

using System.ServiceModel;

 

[ServiceContract()]

public interface IHelloWorldContract

{

    [OperationContract]

    string HelloWorld();

 

    [OperationContract]

    string HelloPerson(string name);

   

}

                  Teraz jak już mamy zdefiniowany kontrakt pozostaje nam go tylko zaimplementować.

d.      Dodajmy sobie nowy plik gdzie będzie deklaracja klasy HelloWorldService implementującej uprzednio stworzony interface. Kod może wyglądać nastepująco:

[Kod C#]

using System;

using System.ServiceModel;

 

public class HelloWorldService : IHelloWorldContract

{

    #region IHelloWorldContract Members

 

    public string HelloWorld()

    {

        return "Hello World";

    }

 

    public string HelloPerson(string name)

    {

        return String.Format("Hello {0} it's your first WCF service", name);

    }

 

    #endregion

}

 

e.      Teraz dodajmy plik konfiguracyjny gdzie umieścimy informacje na temat adresu i binding’u tworzonego endpoint’a.  Poniższy kod dodajemy w sekcji configuration.

[Kod C#]

<system.serviceModel>

   <services>

            <service behaviorConfiguration="NewBehavior" name="WCFTest.HelloWorldService">

                <endpoint address="http://localhost/HelloWorldService/Ep1" binding="basicHttpBinding"

                    name="Ep1" contract="WCFTest.IHelloWorldContract" />

            </service>

        </services>         

</system.serviceModel>

f.        Następnie dodajemy kolejny plik do hostowania naszej aplikacji. Dodajemy zwykły plik z klasą i dodajemy do niego metodę statyczną static void Main(), która będzie stanowiła jako punkt wejściowy do naszego projektu. Teraz wewnątrz tej klasy utworzmy metode statyczną RunServiceFromConfig, która utworzy obiekt typu ServiceHost w konstruktorze podając typ klasy implementującej nasz kontrakt a zaraz po tym wywołanie metod Open() i Close() gdy będziemy chcieli zakończyć nasłuchiwanie. A następnie w funkcji Main wywołać tą metodę. Przykładowy kod może wyglądać tak:

 

 

[Kod C#]

private static void RunServiceFromConfig()

        {

            using (ServiceHost sh = new ServiceHost(typeof(HelloWorldService)))

            {

                sh.Open();

                Console.WriteLine("Serivce is running...");

                Console.ReadKey();

                Console.WriteLine("closing service");

                sh.Close();

            }

        }

Teraz service host po inicjalizacji sprawdza plik konfiguracyjny w poszukiwaniu endpoint’ów, które serwisowi podanemu w konstruktorze i uruchamia je.

g.       Warto zaznaczyć, że endpoint’y możemy również definiować w kodzie poprzez wywołanie metody obiektTypuServiceHost.AddServiceEndpoint(), gdzie jako parametry podaje się kontrakt, URI oraz Binding. Przykładowe wywołanie może wyglądać tak:

[Kod C#]

sh.AddServiceEndpoint(typeof(IHelloWorldContract),

                    new WSHttpBinding(),

                    "http://localhost/HelloWorldService/Ep2");

Dodawanie endpoint’ów w kodzie ma swoje wady i zalety.  Wadą jest fakt, że aby dodać lub zmodyfikować jakiś endpoint trzeba przebudować projekt, zaletą jest fakt, że kompilator sprawdzi czy nie ma jakiejś literówki. Plik konfiguracyjny za to zaakceptuje każdą wartość i o błędzie dowiemy się dopiero w przypadku uruchomienia kodu, który wykorzystuje te złe wpisy.

Na szczęście jest narzędzie o nazwie Service Confiuration Editor, które generuje plik konfiguracyjny na podstawie ustawień wprowadzonych w programie. Narzędzie to jest bardzo łatwe i zapobiega literówkom, jakie mogłyby powstać przy pisaniu tych elementów ręcznie. Jest ono częścią Windows Vista SDK, które można ściągnąć za darmo ze strony firmy Microsoft.

h.      Jeśli wszystko poszło dobrze powinniśmy zobaczyć okno symbolizujące rozpoczęcie serwisu WCF.

Klient

1.       Teraz skoro mamy już aplikację stworzoną w technologii WCF udostępniającą funkcjonalności nadszedł czas, aby stworzyć klienta korzystającego z tych funkcjonalności.

2.       Stwórzmy nowy projekt typu ConsoleApplication o nazwie WCFClientApp. Do projektu dołączamy referencję do System.ServiceModel.

3.       Aby połączyć się z wcześniej stworzonym serwisem wygenerujemy kod za pomocą narzędzia, svcutil. Jednak, aby tego dokonać musimy ustawić, aby serwis udostępniał meta-dane, ponieważ domyślnie tego nie robi.

4.       Wracamy do pliku konfiguracyjnego serwisu i modyfikujemy go dodając pewne zachowanie związane z meta-danymi.

[Kod C#]

<configuration>

    <system.serviceModel>

        <behaviors>

            <serviceBehaviors>

                <behavior name="NewBehavior">

                    <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost/HelloWorldService/Ep1/wsdl"/>

                </behavior>

            </serviceBehaviors>

        </behaviors>

        <bindings />

        <services>

            <service behaviorConfiguration="NewBehavior" name="WCFTest.HelloWorldService">

                <endpoint address="http://localhost/HelloWorldService/Ep1" binding="basicHttpBinding"

                    name="Ep1" contract="WCFTest.IHelloWorldContract" />

            </service>

        </services>

    </system.serviceModel>

</configuration>

5.       Teraz uruchamiamy nasz serwis i wchodzimy do linii poleceń z Vista SDK i wpisujemy komendę:

svcutil http://localhost/HelloWorldService/Ep1/wsdl

Ta komenda wygeneruje nam pliki (w katalogu, w którym wywołaliśmy tą komendę, ewentualnie możemy skorzystać z parametru /out: i /config: i ręcznie ustalić nazwę i ścieżkę):

 HelloWorldService.cs – plik z kodem do połączenia z serwisem

output.config – plik konfiguracyjny z parametrami serwisu

Teraz kopiujemy te pliki do katalogu, w którym został utworzony projekt kliencki.

6.       Wracamy do Visual Studio i dołączamy te pliki do projektu klienckiego (Project/Add Existing Item). 

7.       Zmieniamy nazwę pliku konfiguracyjnego z output.config na App.config

8.       W metodzie Main tworzymy obiekt klasy HelloWorldContractClient (nazwa klasy jest różna zależna od serwisu, z jakiego tworzyliśmy te pliki), dzięki któremu będziemy mogli wywoływać metody serwisu. Teraz dodajemy kod wywołujący te funkcje, może on wyglądać przykładowo tak:

[Kod C#]

using (HelloWorldContractClient client = new HelloWorldContractClient())

   {

                Console.WriteLine(client.HelloWorld());

                Console.Write("Podaj swoje imię: ");

                string name = Console.ReadLine();

                Console.WriteLine(client.HelloPerson(name));

                Console.ReadKey();

}

Uruchamiamy najpierw serwis a następnie dopiero klienta i obserwujemy działanie.

 

Podsumowanie

Jak mogliśmy zauważyć bardzo dużo opcji może być ustawionych w pliku konfiguracyjnym, co umożliwia nam dodanie pewnych elementów (nowych endpoint’ów) lub modyfikować (np. protokoły, szyfrowanie itp.) co nie powoduje konieczności przebudowania projektu. Dzięki temu szczegóły związane z transportem są kompletnie niezależne od logiki serwisu. Co więcej mamy teraz prosty i ujednolicony model programowania dla różnych metod komunikacji.  

 

Źródła

Podobne artykuły

Komentarze 0

pkt.

Zaloguj się lub Zarejestruj się aby wykonać tę czynność.