windows communication foundation

132
Windows Communication Foundation Bartłomiej Zass ISV Developer Evangelist Microsoft

Upload: bartlomiej-zass

Post on 24-Jun-2015

748 views

Category:

Documents


0 download

DESCRIPTION

Przegląd najważniejszych elementów Windows Communication Foundation (WCF). Od wprowadzenia przez bardziej szczegółowe omówienie koncepcji bindingów, kontraktów, sposobów instancjonowania, obsługi błędów, bezpieczeństwa, itp.

TRANSCRIPT

Page 1: Windows Communication Foundation

Windows Communication Foundation

Bartłomiej ZassISV Developer EvangelistMicrosoft

Page 2: Windows Communication Foundation

Od obiektów do usług

PolimorfizmHermetyzacjaDziedziczenie

KomunikatSchemat + kontrakt + polisaSzeroka współpraca

Położenie dowolneŚcisły związekMetadane w czasie działania

Obiektowe UsługiKomponentowe

1980 20001990

Page 3: Windows Communication Foundation

Zadania serwera aplikacyjnego

• „Pojemnik” na obiekty realizujące daną funkcjonalność– Jak pisać logikę obiektów?

• Infrastruktura: transakcje, sesje, stan…• Mechanizmy komunikacji• Skalowalność: platforma + „opcje dla programisty”• Administrator:

– Nadzór nad działaniem „platformowym”• Zużycie pamięci, procesora, wątki itp.

– Monitorowanie działania „biznesowego”• O ile będzie rejestrowane w zrozumiały sposób…

Serwer aplikacyjny to urządzenie które dostarcza aplikację do urządzeń klienckich (za Wikipedia).Komputer dedykowany do wykonania określonych programów/zadań.

+ architektura

Page 4: Windows Communication Foundation

MTSKomponentyRuntime aplikacjiDeklaratywne transakcje i bezpieczeństwoAutoryzacja oparta o role

COM+ Luźno powiązane zdarzeniaKomponentyu kolejkowane„przepustnica” – nie więcej niż x komponentów

Enterprise ServicesModel programowania w kodzie zarządzalnymOparty o atrybuty, deklaratywny, konfiguracja w XML

Windows Communication Foundation• Komunikaty oparte o XML• Dowolny transport• Zorientowane na usługi• Bezpieczeństwo: Federacja, CardSpace

(dowody tożsamości)• Hosting - gdziekolwiek

Ewolucja usług aplikacyjnych

Page 5: Windows Communication Foundation

-2002 2002-2006 2006-

Problem – komunikacja…

Page 6: Windows Communication Foundation

4 podstawowe doktryny SOA

Wyraźne granice

Usługi są autonomiczne

Usługi dzielą kontrakt nie klasę

Kompatybilność określana przez

policy

Page 7: Windows Communication Foundation

Wprowadzenie do WCF

Page 8: Windows Communication Foundation

WCF: Adres, Binding, Kontrakt

Klient Usługa

KomunikatABC A B C

A B C

Adres Binding Kontrakt

(Gdzie) (Jak) (Co)

Endpoint

Endpoint

Endpoint

EncoderTransport

BasicHttp, WSHttp, WSDualHttp,

WSFederation…Context…

NetTcp, NetNamedPipe,

NetPeerTcp

NetMsmq, MsmqIntegration

Page 9: Windows Communication Foundation

WCF – standardowe bindingiBinding Interop Bezp. Sesja Trans. Duple

x BasicHttpBinding BP 1.1 N, T N N n/a

WSHttpBinding WS M, T, X N, T, RS N, Tak n/a

WSDualHttpBinding WS M RS N, Tak Tak

WSFederationBinding Federacja M N, RS N, Tak Nie

NetTcpBinding .NET T, M T ,RS N, Tak Tak

NetNamedPipeBinding .NET T T, N N, Tak Tak

NetPeerTcpBinding Peer T N N Tak

NetMsmqBinding .NET T, M, X N N, Tak Nie

MsmqIntegrationBinding MSMQ T N N, Tak n/a

N = Brak | T = Transport | M = Wiadomość | B = Oba | RS = Pewna sesja

Page 10: Windows Communication Foundation

WCF – podstawy (wyjaśnienie)

• Separacja kontraktu i implementacji• Wzorce komunikacyjne

– Komunikacja jednokierunkowa (IsOneWay)– Zwracanie wartości– Sesja,– Kontrakt „zwrotny” (po stronie klienta)– Kontekst

• Separacja szczegółów komunikacyjnych• Hosting: Jakkolwiek

Page 11: Windows Communication Foundation

WCF na jednym slajdzie

Definicja „końcówki”Adres + Binding +

Kontrakt

Definicja kontraktu

Implementacja usługi

[ServiceContract]public interface IMyInterface {

[OperationContract]void MyMethod();

[ServiceBehavior(InstanceContextMode=Single]public class MyService: IMyInterface {[OperationBehavior(Impersonation = ImpersonationOption.Required)]public void MyMethod() { … }

<service name="MyService"> <endpoint address=“net.tcp://localhost:1234/MySvc" binding="netTcpBinding" contract="IMyInterface" />o

Page 12: Windows Communication Foundation

Kontrakt

• Definiują funkcjonalność usługi. • Atrybuty kontraktu:

– ServiceContract• OperationContract

– DataContract– FaultContract– MessageContract

• MessageBody• MessageHeader

• Zachowania kontraktu– Sesja, transakcje, sposób inicjacji…

Page 13: Windows Communication Foundation

Kontrakt

• Możliwość implementacji wielu kontraktów• Publiczny konstruktor• [ServiceContract(Namespace = „”)]

– Domyślnie – tempuri.org– Intranet – np. nazwa aplikacji– Intenet – URL

• Nazwa metody usługi – domyślnie z klasy– [OperationContract(Name = „…”)]

Page 14: Windows Communication Foundation

Host

• IIS + WAS (Vista+, Windows Server 2008+)– Zarządzanie, skalowalność, itp.

• IIS 5/6 – tylko HTTP– Web.config – eksponowane usługi

• Self-hosting– InProc – szczególny przypadek (klient i serwer w

tym samym procesie)– Między procesami– Między maszynami

Page 15: Windows Communication Foundation

ServiceHost

public static void Main( ){ Uri baseAddress1 = new Uri("net. tcp: //localhost: 8001/"); ServiceHost host1 = new ServiceHost(typeof(MyService), baseAddress1) ; ServiceHost host = new ServiceHost(typeof(MyService)); host.Open( );

//Możliwe blokujące wywołania Application.Run(new MyForm( )); host.Close( );}

// WcfSvcHost

Page 16: Windows Communication Foundation

WAS

• Nie ograniczony do HTTP– Dowolny transport, port, kolejka

• Zalety vs self-hosting– Application pooling, recycling, zarządzanie idle-

time, izolacja– Zalecane, kiedy dostępne Windows Server 2008

• Interakcja z procesem hosta<%@ ServiceHost

Language = "C#" Debug = "true" CodeBehind = "~/App_Code/MyService. cs" Service = "MyService" Factory = "MyServiceFactory" %>

Page 17: Windows Communication Foundation

Service Factory

class MyServiceFactory : ServiceHostFactory{ protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { ServiceHost host = new ServiceHost(serviceType,

baseAddresses);

// Dodatkowe kroki – np. logowanie return host; }}

Page 18: Windows Communication Foundation

Bindingi

• Protokół (HTTP, TCP, IPC, MSMQ)• Enkodowanie (plain text, MTOM)• Bezpieczeństwo (transport, komunikat)• …

Page 19: Windows Communication Foundation

Inne popularne bindingi

• NetPeerTcpBinding• WSFederationHttpBinding• WS2007FederationHttpBinding• MsmqIntegrationBinding• WebHttpBinding• WS2007HttpBinding

Page 20: Windows Communication Foundation

Wybór bindingu

Page 21: Windows Communication Foundation

Endpoint

• „Końcówka”, z którą możemy się komunikować– Przynajmniej jeden dla każdej usługi

• Dokładnie jeden kontrakt

Page 22: Windows Communication Foundation

Endpointy - konfiguracja<system.serviceModel = ""> <services> <service name = "MyNamespace.MyService"> <endpoint address = "http://localhost:8000/MyService" binding = "wsHttpBinding" contract = "MyNamespace.IMyContract„

bindingConfiguration = "TransactionalTCP /> </service> </services>

<!–- <bindings> <netTcpBinding>    <binding name = "TransactionalTCP"       transactionFlow = "true" /> </netTcpBinding>

</bindings> -->

</system.serviceModel>

Page 23: Windows Communication Foundation

Metadane• Domyślnie – nie publikowane (nie przeszkadza w działaniu)• Dedykowany endpoint (MEX)

– Eksponowany w dowolny sposób (HTTP, TCP, IPC)

<endpoint address = "http: //localhost: 8000/MEX" binding = "mexHttpBinding" contract = "IMetadataExchange" />

• HTTP-GET (nie ma gwarancji interop)

<behaviors> <serviceBehaviors>

<behavior name = "MEXGET"> <serviceMetadata httpGetEnabled = "true"/> </behavior>

</serviceBehaviors> </behaviors>

Page 24: Windows Communication Foundation

Po stronie klienta

• Add service reference – automatycznie• SvcUtil

SvcUtil http://localhost:8000/MEX /out:Proxy.cs

• WcfTestClient. exe http: //localhost:9000/• Ręcznie - kodpublic abstract class ClientBase<T> : ICommunicationObject, IDisposable{ protected ClientBase(string endpointName); protected ClientBase(Binding binding, EndpointAddress remoteAddress); public void Open(); public void Close(); protected T Channel { get; } //...}

Page 25: Windows Communication Foundation

[ServiceContract(Namespace = "MyNamespace")]interface IMyContract{ [OperationContract] void MyMethod();}

partial class MyContractClient : ClientBase<IMyContract>, IMyContract{ public MyContractClient() { } public MyContractClient(string endpointName) : base(endpointName) { } public MyContractClient(Binding binding, EndpointAddress remoteAddress) : base(binding, remoteAddress) { } /* Dodatkowe konstruktory */ public void MyMethod() { Channel.MyMethod(); }}

Page 26: Windows Communication Foundation

Wywoływanie usługi

MyContractClient proxy = new MyContractClient("MyEndpoint");proxy.MyMethod( );proxy.Close( );

// Można również using…

Page 27: Windows Communication Foundation

Bez generacji kodu - ChannelFactory

Binding binding = new NetTcpBinding( );

EndpointAddress address = new EndpointAddress("net.tcp://localhost:8000");

IMyContract proxy = 

ChannelFactory<IMyContract>.CreateChannel(binding, address) ;

using(proxy as IDisposable) {    

proxy.MyMethod( ); }

Page 28: Windows Communication Foundation

Transport session• Niektóre bindingi (np. basic – nie)• Mapowanie komunikatu na konkretny kontekst wywołujący

operacje usługi• Reliability

– Transport reliability – pakiety, itp.– Message reliability – kolejność (domyślnie) i informowanie kiedy nie

dostarczono (ponawianie, itp.)

<binding name = "ReliableTCP"> <reliableSession enabled = "true"/>

</binding>

Page 29: Windows Communication Foundation

Kolejność komunikatów• Nie powinniśmy wymagać konkretnego bindingu, ale czasem

istotna jest kolejność.

[DeliveryRequirements(TargetContract = typeof(IMyContract), RequireOrderedDelivery = true) ]

class MyService : IMyContract, IMyOtherContract { ... }

[ServiceContract] [DeliveryRequirements(RequireOrderedDelivery = true) ] interface IMyContract { ... }

Page 30: Windows Communication Foundation

Kontrakt

Page 31: Windows Communication Foundation

Overloading

// Błąd!

[ServiceContract]interface ICalculator{    [OperationContract]    int Add(int arg1, int arg2);

    [OperationContract]    double Add(double arg1, double arg2);}

// Rozwiązanie:// [OperationContract(Name = „AddInt”)]

// Proxy: AddInt -> również możliwa ręczna zmiana// nazw i OperationContract

Page 32: Windows Communication Foundation

Dziedziczenie• Możliwe, ale [ServiceContract] nie jest dziedziczony

[ServiceContract]interface ISimpleCalculator{ [OperationContract] int Add(int arg1, int arg2);}[ServiceContract]interface IScientificCalculator : ISimpleCalculator{ [OperationContract] int Multiply(int arg1, int arg2);}

// „Spłaszczane” po stronie klienta// Możliwe ręczne przywrócenie hierarchii po stronie klienta i usunięcie atrybutów// [OperationContract]

[OperationContract(Action = "... /ISimpleCalculator/Add", ReplyAction = "... /ISimpleCalculator/AddResponse")]

int Add(int arg1, int arg2) ;

[OperationContract(Action = "... /IScientificCalculator/Multiply",

ReplyAction = "... /IScientificCalculator/MultiplyResponse")] int Multiply(int arg1, int arg2) ;

Page 33: Windows Communication Foundation

Zgodność z kontraktem// Dynamiczna weryfikacja zgodności na podstawie WSDL

bool contractSupported = false; Uri mexAddress = new Uri("...?WSDL") ;

ServiceEndpointCollection endpoints = MetadataResolver. Resolve(typeof(ISimpleCalculator) ,

exAddress, MetadataExchangeClientMode. HttpGet) ;

if(endpoints. Count > 0) {

contractSupported = true; }

Page 34: Windows Communication Foundation

Kontrakty danych

Page 35: Windows Communication Foundation

Wymiana danych

• Infoset – obsługiwane typy parametrów, …• Serializacja w .NET

– [Serializable], [NonSerialized]– BinaryFormatter, SoapFormatter – wymaga .NET i

konkretnego typu– WCF – DataContractSerializer – nie udostępnia

informacji o typie; tylko kontrakt danych• Wyłącznie serializowalne typy

– Klasa musi być dostępna także po stronie klienta

Page 36: Windows Communication Foundation

Atrybuty kontraktu danych

• Samo [Serializable] – zbyt ścisłe powiązanie• [DataContract]

– Publikowane w MEX

[DataContract]struct Contact{    [DataMember]    public string FirstName;

    [DataMember]    public string LastName;}// *Dla uproszczenia bez właściwości// Właściwości mogą być private, koniecznie get i set

Page 37: Windows Communication Foundation

Zdarzenia serializacji

• Np. inicjalizacja• [OnSerializing], [OnSerialized]

[OnDeserializing], [OnDeserialized]

[DataContract]class MyDataContract{

[OnSerializing] void OnSerializing(StreamingContext context) {. . .}

}

Page 38: Windows Communication Foundation

Inne• Współdzielenie kontraktu

– Problem: ten sam typ w 2 serwisach (przestrzenie nazw)– „Reuse types in reference assemblies”

• Dziedziczenie– [KnownType], [ServiceKnownType]

// Customer : ContactContact contact = new Customer( ); ContactManagerClient proxy = new ContactManagerClient( );

// Błąd w czasie działaniaproxy.AddContact(contact) ; proxy.Close( );

// ------------------------

[DataContract][KnownType(typeof(Customer))]class Contact { ... }

[DataContract]class Customer : Contact { ... }

Page 39: Windows Communication Foundation

Współdzielenie kontraktu

• Zgodność z infoset - np. wersjonowanie• Dostosowanie klasy właściwością Name

[DataContract(Name = "Contact")]struct Person{    [DataMember(Name = "FirstName")]    public string Name;    [DataMember(Name = "LastName")]    public string Surname;}

Page 40: Windows Communication Foundation

Współdzielenie a serializacja (1)

• Od najbardziej ogólnej do najbardziej szczegółowej

• Pola – alfabetycznie

[DataContract] class Contact {     [DataMember]     public string FirstName;   [DataMember]   public string LastName;}[DataContract]class Customer : Contact{    [DataMember]    public int CustomerNumber;}// Infoset: Firstname, Lastname, CustomerNumber

Page 41: Windows Communication Foundation

Współdzielenie a serializacja (2)[DataContract(Name = "Customer")]public class Person{    [DataMember(Name = "FirstName")]    public string Name;    [DataMember(Name = "LastName")]    public string Surname;    [DataMember]    public int CustomerNumber;}// Kolejność: CustomerNumber, Firstname, Lastname

[DataContract(Name = "Customer")]public class Person{ [DataMember(Name = "FirstName", Order = 1)] public string Name; [DataMember(Name = "LastName", Order = 1)] public string Surname; [DataMember(Order = 2)] public int CustomerNumber;}// Kolejność zgodna z infoset: Firstname, Lastname, CustomerNumber

Page 42: Windows Communication Foundation

Wersjonowanie kontraktu

• Dodawanie nowych pól– Nadmiarowość jest dozwolona i kompatybilna

• Brakujące pola– Wartości domyślne (null, itp.)– [OnDeserializing]– [DataMember(IsRequired = true)] – wyjątek– Problem z przekazywaniem dalej – utracona

informacja

Page 43: Windows Communication Foundation

Wersjonowanie c.d.[DataContract]class Contact : IExtensibleDataObject{    ExtensionDataObject IExtensibleDataObject.ExtensionData    { get; set; }

    [DataMember]    public string FirstName;    [DataMember]    public string LastName;}// Nie tracimy nadmiarowej informacji

// Umożliwia to interakcję z serwisem spodziewającym się innego// kontraktu. Dlatego można wykluczyć taki scenariusz:

[ServiceBehavior(IgnoreExtensionDataObject = true)] class ContactManager : IContactManager { ... }

// Najlepsza praktyka: zawsze obsługa IExtensibleDataObject// unikać IgnoreExtensionDataObject

Page 44: Windows Communication Foundation

Sposoby instancjonowania

Page 45: Windows Communication Foundation

Kontekst

Page 46: Windows Communication Foundation

Zarządzanie kontekstem

• Tryby instancjonowania kontekstów• Per Call• Per Session• Singleton

Page 47: Windows Communication Foundation

Per Call

• Bezstanowość, skalowalność– Konieczna inicjalizacja i zapis stanu

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]class MyService : IMyContract{ ... }

Page 48: Windows Communication Foundation

[ServiceContract]interface IMyContract{ [OperationContract] void MyMethod( );}[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall) ]class MyService : IMyContract, IDisposable{ int m_Counter = 0; MyService( ) { Trace. WriteLine("MyService. MyService( )"); } public void MyMethod( ) { m_Counter++; Trace. WriteLine("Counter = " + m_Counter) ; } public void Dispose( ) { Trace. WriteLine("MyService. Dispose( )"); }}///////////////////////// Client Code /////////////////////MyContractClient proxy = new MyContractClient( );proxy.MyMethod( );proxy.MyMethod( );proxy.Close( );// Wyjście:MyService.MyService( )Counter = 1MyService.Dispose( )MyService.MyService( )Counter = 1MyService.Dispose( )

Page 49: Windows Communication Foundation

Per Call i sesja komunikacyjna

• Jeśli serwis ma tryb single-threaded i włączone transport session, żądania przetwarzane jeden po drugim– Bez sesji – możliwa losowa kolejność na wyjściu

• Uwaga: Load Balancer i sesja– Sticky Sessions

Page 50: Windows Communication Foundation

Per Session• Domyślny tryb• Instancja utrzymywana w pamięci

– Skalowalność

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] class MyService : IMyContract { ... }

• Wymagane transport session– Zalecane wymuszenie na poziomie kontraktu

public enum SessionMode{    Allowed,    Required,    NotAllowed}

[ServiceContract(SessionMode = SessionMode.Allowed)] interface IMyContract {. . . }

Page 51: Windows Communication Foundation

Singleton

• Tworzony wraz ze startem procesu hosta• Sesja nie wymagana

– Po zakończeniu, nadal instancja w pamięci

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] class MyService : IMyContract { ... }

• Możliwe przekazanie zainicjalizowanej instancji klasy do konstruktora hosta

Page 52: Windows Communication Foundation

Sesja a kontrakt

• Atrybuty gwarantujące prawidłową kolejność wywołań

[ServiceContract(SessionMode = SessionMode.Required)]interface IMyContract{ [OperationContract] void StartSession(); [OperationContract(IsInitiating = false)] void CannotStart(); [OperationContract(IsTerminating = true)] void EndSession(); [OperationContract(IsInitiating = false, IsTerminating = true)] void CannotStartCanEndSession();}

Page 53: Windows Communication Foundation

Zwalnianie kontekstu

• ReleaseInstanceMode.BeforeCall• ReleaseInstanceMode.AfterCall• ReleaseInstanceMode.BeforeAndAfterCall

Page 54: Windows Communication Foundation

Durable services• Długotrwałe procesy

– Wywołanie – długi czas oczekiwania - wywołanie• Trwałe zapisywane stanu (np. baza danych)

– Serializacja – deserializacja– Provider (domyślny lub własny)

• ID instancji– Komunikaty aktywacyjne (jeśli brak ID)– Komunikaty kończące (usunięcie instancji)

<behaviors> <serviceBehaviors> <behavior name = "DurableService"> <persistenceProvider type = "... type ... , ... assembly ... " <!-- Provider-specific parameters --> /> </behavior> </serviceBehaviors></behaviors>

Page 55: Windows Communication Foundation

[Serializable][DurableService]class MyCalculator : ICalculator{ double Memory { get; set; }

[DurableOperation(CanCreateInstance = true)] public double Add(double number1, double number2) { return number1 + number2; } public void MemoryStore(double number) { Memory = number; }

[DurableOperation(CompletesInstance = true)] public void MemoryClear() { Memory = 0; } //Rest of the implementation}

Page 56: Windows Communication Foundation

Throttling• Tymczasowe piki w obciążeniu

– Kolejkowanie, spłaszczenie piku

• Nie działa w przypadku stałego zwiększenia obciążenia

• Możliwe do konfiguracji: maxConcurrentCalls, maxConcurrentSessions, maxConcurrentInstances

Page 57: Windows Communication Foundation

Operacje

Page 58: Windows Communication Foundation

One-way

• [OperationContract(IsOneWay = true)]– Przed metodą usługi– Domyślnie – false– Metoda musi zwracać void (inaczej błąd)

• Wyjątki usługi nie dotrą do klienta• Błędy komunikacyjne nadal się pojawiają• Jeśli reliablesession (transport session) – wtedy jest

przerywana

• Najlepsza praktyka: tylko PerCall i Singleton

Page 59: Windows Communication Foundation

Operacje duplex

• Niektóre bindingi– WSDualHttpBinding, NetTcpBinding, NetNamedPipeBinding– Nie jest standardem

• Odpowiedź wywoływana przez serwis na klasie klienta– WSDualHttpBinfing - domyślnie port 80 (możliwa zmiana)

• Wywołanie natychmiastowe lub referencja na poźniej

IMyContractCallback callback = OperationContext.Current.GetCallbackChannel<IMyContractCallback>( );

interface ISomeCallbackContract{ [OperationContract] void OnCallback();}[ServiceContract(CallbackContract = typeof(ISomeCallbackContract))]interface IMyContract{ [OperationContract] void DoSomething();}

Page 60: Windows Communication Foundation

Po stronie klienta

class MyCallback : IMyContractCallback {     public void OnCallback( )     { ... } }

IMyContractCallback callback = new MyCallback(); InstanceContext context = new InstanceContext(callback); MyContractClient proxy = new MyContractClient(context) ; proxy.DoSomething();

Page 61: Windows Communication Foundation

Callback

• Wywoływanie callbacku w operacji usługi– Domyślnie 1 wątek ma dostęp do metod– W trakcie wywoływanej operacji lock na instancję

kontekstu– Po wywołaniu callback – odpowiedź do serwera na

ten sam (zablokowany) kanał• ConcurrencyMode

– Single– Multiple – ok, kłopoty z synchronizacją– Reentrant – ok

• Lub: metody OneWay (brak odpowiedzi)

Page 62: Windows Communication Foundation

Streaming

• Klasyczne wywołania – buforowane po stronie serwera– Blokowanie do czasu zakończenia przesyłania

komunikatu• Streaming (wyłącznie klasa Stream)

– Niektóre bindingi (TCP, IPC, Basic HTTP)– Niemożliwy do wykorzystania z message-level security<bindings>

<basicHttpBinding> <binding name = "StreamedHTTP"

transferMode = "Streamed„ maxReceivedMessageSize = "120000"/>

</basicHttpBinding> </bindings>

Page 63: Windows Communication Foundation

Streaming c.d.[ ServiceContract] interface IMyContract {    

[OperationContract] Stream StreamReply1( );    

[OperationContract]    void StreamReply2(out Stream stream) ;    

[OperationContract]    void StreamRequest(Stream stream) ;

[OperationContract(IsOneWay = true)]void OneWayStream(Stream stream);

}

Page 64: Windows Communication Foundation

Błędy

Page 65: Windows Communication Foundation

Podstawy

• Błędy komunikacyjne i kanałów• Błędy po stronie serwisu

– Izolacja błędów od klienta!• Jeśli jest sesja – automatycznie stan kanału

CommunicationState.Faulted

// w klasycznym .NET ok – tu CommunicationObjectFaultedException// uwaga na using!- po dispose nowa instancja proxy

IMyContract obj = new MyClass( );try{ obj.MyMethod( );}catch{}obj.MyMethod( );

Page 66: Windows Communication Foundation

Propagacja błędów

• Ustandaryzowane – SOAP fault• FaultException<T>

class Calculator : ICalculator{    public double Divide(double number1, double number2)    {        if (number2 == 0)        {            DivideByZeroException exception = new DivideByZeroException();            throw new FaultException<DivideByZeroException>(exception);        }        return number1 / number2;    }}

Page 67: Windows Communication Foundation

Kontrakty błędów• Każdy błąd dociera do klienta jako FaultException

– Także FaultException<T> (dziedziczy po FaultException)– Wszystko co jest wymieniane musi być w kontrakcie

• [FaultContract]– Musi być dokładnie klasa błędu– Nie może być to nawet klasa dziedzicząca!– Może być kilka – dla kilku typów– Nie można aplikować dla operacji OneWay (błąd)– Nie zamyka kanału komunikacji (każdy dziedziczący po FaultException)

• Kontrakt publikowany w metadanych– Klasy błędów importowane podczas generacji proxy

• IErrorHandler

[OperationContract]    [FaultContract(typeof(DivideByZeroException))]    double Divide(double number1, double number2)    { ... }   

// jeśli typeof(Exception) -może być tylko throw Exception!

Page 68: Windows Communication Foundation

Debugowanie - ExceptionDetail[ServiceBehavior(IncludeExceptionDetailInFaults = true)]class MyService : IMyContract{ public void MethodWithError() { throw new InvalidOperationException("Some error"); }}

// ---------------------------------------

MyContractClient proxy = new MyContractClient( );try{ proxy.MethodWithError( );}catch(FaultException<ExceptionDetail> exception){ Debug.Assert(exception.Detail.Type == typeof(InvalidOperationException).ToString( )); Debug.Assert(exception.Message == "Some error") ;}

// Może być ustawiane ręcznie / w konfiguracji hosta (debugowanie istniejącego serwisu!)// Uwaga przy deployment!

Page 69: Windows Communication Foundation

Transakcje

Page 70: Windows Communication Foundation

Transakcje• Wymagane zasoby transakcyjne

– WCF Resource Managers– Np. baza danych czy kolejka MSMQ, Volatile Resource Managers– http://msdn.microsoft.com/en-us/magazine/cc163688.aspx#S8

• Transakcje rozproszone– Two-phase commit i transaction manager– 1 faza: voting, 2 faza: faktyczny commit

• Protokoły (wybór automatyczny)– Lightweight – app domain– OleTX – intranet– WS-Atomic Trnsaction (WSAT) - internet

Page 71: Windows Communication Foundation

Propagacja transakcji

• Obsługują wybrane bindingi– TCP, IPC, WS http

• Domyślnie – wyłączone– Konieczne włączenie po stronie klienta i serwera

• Sesja – nie wymagana, ale zalecana

<bindings> <netTcpBinding> <binding name = "TransactionalTCP" transactionFlow = "true" /> </netTcpBinding></bindings>

Page 72: Windows Communication Foundation

Propagacja transakcji c.d.

• Nie wszystkie operacje muszą obsługiwać transakcje• [TransactionFlow]

– Allowed– NotAllowed– Mandatory

• Operacje OneWay – błąd

[ServiceContract]interface IMyContract{    [OperationContract]    [TransactionFlow(TransactionFlowOption.Allowed)]    void MyMethod();}

Page 73: Windows Communication Foundation

Transaction Manager• Nadzoruje transakcję• Lightweight Transaction Manager (LTM)

– AppDomain, SQL 2005/2008• Kernel Transaction Manager (KTM)

– Vista / Windows Server 2008– KRM: Transactional file system (TxF), Transaction registry (TxR)– Tylko jeden serwis

• Distributed Transaction Coordinator (DTC)– Wykorzystywany w transakcjach rozproszonych– OleTX / WSAT

• Każda transakcja najpierw zarządzana przez LTM– Jeśli więcej usług / zasobów – promocja do DTC– Jeśli zasób KRM – promocja do KTM

Page 74: Windows Communication Foundation

Transakcja z DTC

Page 75: Windows Communication Foundation

Ambient transaction

• Transakcje wewnątrz thread local storage (TLS)– Transaction t = Transaction.Current;

• Automatyczne przenoszenie transakcji na stronę usługi• Transaction Scope

class MyService : IMyContract{    [OperationBehavior(TransactionScopeRequired = true)]    public void MyMethod()     {       Transaction transaction = Transaction.Current;       Debug.Assert(transaction != null);     }}

Page 76: Windows Communication Foundation

Przykładowy przepływ

Page 77: Windows Communication Foundation

Głosowanie (commit)

• Deklaratywnie – Zalecane– domyślnie TransactionAutoComplete = true– Jeśli mamy strukturę try-catch, wyrzucić wyjątek dalej

[OperationBehavior(TransactionScopeRequired = true,  TransactionAutoComplete = true)]

public void MyMethod( ) { ... }

[OperationBehavior(TransactionScopeRequired = true)] public void MyMethod( )

{ ... }

Page 78: Windows Communication Foundation

Głosowanie (kod)• Zatwierdzenie powinno być ostatnim wywołaniem w metodzie

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false) ]

public void MyMethod( ){ try { /* Na koniec: */ OperationContext.Current.SetTransactionComplete( ); } catch { /* np. logowanie, następnie: */ throw; }}

Page 79: Windows Communication Foundation

Izolacja transakcji

• Domyślnie – Unspecified– Wykorzystywany poziom transakcji klienta

• Jeśli inny – klient musi mieć zadeklarowany poziom transakcji taki sam (inaczej błąd)

class MyService : IMyContract { ... }

[ServiceBehavior(TransactionIsolationLevel =  IsolationLevel.Unspecified)]

class MyService : IMyContract

{ ... }

Page 80: Windows Communication Foundation

Klientusing (TransactionScope scope = new TransactionScope()){ MyContractClient proxy1 = new MyContractClient( ); proxy1.MyMethod( ); proxy1.Close( ); MyOtherContractClient proxy2 = new MyOtherContractClient( ); proxy2.MyOtherMethod( ); proxy2.Close( ); scope.Complete( );}

Page 81: Windows Communication Foundation

Instancjonowanie PerCallMyContractClient proxy = new MyContractClient( );using(TransactionScope scope = new TransactionScope( )){ proxy.MyMethod( ... ) ; proxy.MyMethod( ... ) ; scope.Complete( );}proxy.Close( );

Page 82: Windows Communication Foundation

Instancjonowanie PerSession

• Domyślnie – podobnie jak PerCall– Po scope.Complete – instancja usuwana– ReleaseServiceInstanceOnTransactionComplete– ConcurrencyMode musi być Single

[ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete = true)]class MyService : IMyContract{ [OperationBehavior(TransactionScopeRequired = true)] public void MyMethod( ) { ... } [OperationBehavior( ... )] public void MyOtherMethod( ) { ... }}

Page 83: Windows Communication Foundation

„Prawdziwe” PerSession• ReleaseServiceInstanceOnTransactionComplete = false• Zapisywanie stanu

– Resource Manager – jako klucz identyfikator sesji OperationContext.Current.SessionId

– Volatile Resource Managers – pola obiektu instancji

Page 84: Windows Communication Foundation

PerSession – c.d.

• Możliwe zrównanie czasu trwania sesji z czasem trwania transakcji– ReleaseServiceInstanceOnTransactionComplete = false– TransactionAutoComplete = false

– Uwaga na timeout• Nie zalecane[ ServiceBehavior(TransactionAutoCompleteOnSessionClose = true) ]

class MyService : IMyContract {. . . }

Page 85: Windows Communication Foundation

Durable Services

• Stan zapisywany w bazie– Transakcja może niechcący przed tym

powstrzymać• Domyślnie – zapisywanie stanu nie jest

częścią transakcji• [SaveStateInOperationTransaction]

– Domyślnie – false– True – aby stan był zarządzany transakcją

Page 86: Windows Communication Foundation

Singleton

• Domyślnie – PerCall– ReleaseServiceInstanceOnTransactionComplete

• Stan w Volatile Resource Managers

Page 87: Windows Communication Foundation

Wielowątkowość

Page 88: Windows Communication Foundation

Tryby• [ServiceBehavior(ConcurrencyMode=…)]

– Single– Reentrant– Multiple

• Single– Domyślny– Tylko jeden wątek na raz

• Multiple– Konieczne synchronizowanie dostępu

• lock { }• [MethodImpl(MethodImplOptions.Synchronized)]• W takim wypadku – niewielki zysk

– Limitowane przez throttle – domyślnie 16 połączeń• Reentrant

Page 89: Windows Communication Foundation

Wątek UI• WPF, Silverlight – Dispatcher

partial class MyForm : Form{ Label m_CounterLabel; public SynchronizationContext MySynchronizationContext { get; set; } public MyForm() { InitializeComponent(); MySynchronizationContext = SynchronizationContext.Current; } void InitializeComponent() { . . . m_CounterLabel = new Label( ); . . . } public int Counter { get { return Convert.ToInt32(m_CounterLabel.Text); } set { m_CounterLabel.Text = value.ToString(); } }}

Page 90: Windows Communication Foundation

Synchronization Context – c.d.[ServiceContract]interface IFormManager{ [OperationContract] void IncrementLabel();}

class MyService : IFormManager{ public void IncrementLabel() { MyForm form = Application.OpenForms[0] as MyForm; Debug. Assert(form ! = null) ; SendOrPostCallback callback = delegate { form.Counter++; }; form.MySynchronizationContext.Send(callback, null); }}

static class Program{ static void Main() { ServiceHost host = new ServiceHost(typeof(MyService)); host.Open(); Application.Run(new MyForm()); host.Close(); }}

Page 91: Windows Communication Foundation

Wątek UI

[ServiceBehavior(UseSynchronizationContext = true)] class MyService : IMyContract {. . . }

• Jeśli wątek uruchamiający usługę ma Synchronization Context, automatycznie kontekst przechodzi do usługi• Form jako usługa (i tak ścisłe powiązanie)

– Form jako callback – ok• Inne rozszerzenia

– Np. Ustawianie priorytetów dla wywołań http://msdn.microsoft.com/en-us/magazine/cc163321.aspx

Page 92: Windows Communication Foundation

Operacje asynchroniczne

• Specjalne pole checkbox podczas dodawania referencji

• Klasycznie jak w .NET– Begin<operacja>, End<operacja>– End – blokuje– Callback– Polling – IsCompleted– Wiele wywołań – WaitAll() i

IAsyncResult.WaitHandle

Page 93: Windows Communication Foundation

Serwisy kolejkowane

Page 94: Windows Communication Foundation

Serwisy kolejkowane

• Dostępność usługi• Load leveling – skolejkowanie „piku”• Kolejkowanie niezależnych operacji

biznesowych• Kompensacja (druga kolejka z wynikami)• Kolejkowanie w WCF

– NetMsmqBinding– Opakowanie komunikatu SOAP w komunikat

MSMQ

Page 95: Windows Communication Foundation

Architektura

• Klient wywołuje proxy• Proxy zapisuje komunikat do kolejki• Usługa netMsmqBinding instaluje Channel Listener• Channel listener powiadamia o komunikacie –

komunikat zdejmowany i przetwarzany

Page 96: Windows Communication Foundation

Kolejkowanie w WCF• Tylko operacje OneWay

– Nie mogą zwracać wartości– Nie mogą zwracać błędów

• Kolejki MSMQ– Public – pomiędzy serwerami w domenie– Private – lokalne, nie wymagają DC– Jeden endpoint = jedna kolejka

• Hosting WAS – nazwa kolejki = nazwa pliku svc– address = "net. msmq: //localhost/private/WASService. svc"

<endpoint    address  = "net.msmq: //localhost/private/MyServiceQueue"    binding  = "netMsmqBinding"    

... />

Page 97: Windows Communication Foundation

Transakcje

• MSMQ uczestniczy w transakcjach (opcja)– Jeśli włączone – komunikaty zapisywane na dysk– Transakcje playback – nasz kod

• Publiczna kolejka i reliable messeging– Kolejka proxy– Automatyczne ponawianie wysłania komunikatu

Page 98: Windows Communication Foundation

Sesja i MSMQ

• SessionMode.Allowed lub SessionMode.NotAllowed – brak sesji– Każdy komunikat pojedynczo

• SessionMode.Required– Sessiongram – pakowanie komunikatów w

„paczkę”– Zachowana kolejność doręczenia

Page 99: Windows Communication Foundation

Instancjonowanie PerCall//Klient using(TransactionScope scope = new TransactionScope( )) {    

MyContractClient proxy = new MyContractClient( );    

proxy.MyMethod( ); //Komunikat wysłany   proxy.MyMethod( ); //Komunikat wysłany   proxy.Close( );    scope.Complete( );

} // Zatwierdzane

• Brak przejścia transakcji na stronę usługi• Każde wywołanie osobno, osobne instancje

Page 100: Windows Communication Foundation

Instancjonowanie PerSessionusing(TransactionScope scope = new TransactionScope( )) {    

MyContractClient proxy = new MyContractClient( );proxy.MyMethod();    proxy.MyMethod();    

proxy.Close( ); //Skomponowano komunikat, zapis.     scope.Complete( ); //Musi być za proxy.Close!! } //Pojedynczy komunikat zapisany

Page 101: Windows Communication Foundation

Instancjonowanie PerSession

• Nie mogą mieć trwającej sesji – Podobnie do PerCall

• Ale - wszystkie komunikaty do tej samej instancji

Page 102: Windows Communication Foundation

Throttling

• Po włączeniu usługi – wszystkie komunikaty na raz– Duża liczba instancji kontekstu – obciążenie

• Umożliwia stopniowe przetwarzanie

Page 103: Windows Communication Foundation

Kiedy pojawią się problemy

• Błędy– Komunikacja– Bezpieczeństwo– Quota– …

• Dead-letter queue (DLQ)– Problem z doręczeniem– Nieudany commit transakcji playback– Przetwarzanie kolejki jak zwykły serwis (kontrakt musi być

ten sam / dziedziczący)

Page 104: Windows Communication Foundation

<! -- Client side --><system. serviceModel> <client> <endpoint address = "net. msmq: //localhost/private/MyServiceQueue" binding = "netMsmqBinding" bindingConfiguration = "MyCustomDLQ" contract = "IMyContract" /> </client> <bindings> <netMsmqBinding> <binding name = "MyCustomDLQ" deadLetterQueue = "Custom" customDeadLetterQueue = "net.msmq: //localhost/private/MyCustomDLQ"> </binding> </netMsmqBinding> </bindings></system. serviceModel><! -- DLQ service side --><system. serviceModel> <services> <service name = "MyDLQService"> <endpoint address = "net.msmq://localhost/private/MyCustomDLQ" binding = "netMsmqBinding" contract = "IMyContract" /> </service> </services></system. serviceModel>

Page 105: Windows Communication Foundation

Komunikaty Poison

• Komunikaty Poison– Nieustanne próby doręczenia– Zawsze błąd– Również usługa z polimorficznym kontraktem

• Możliwe akcje– Drop – odrzucenie i potwierdzenie, że dostarczono– Reject – odrzucenie i NACK– Move – przeniesienie do odpowiedniej kolejki

Page 106: Windows Communication Foundation
Page 107: Windows Communication Foundation

Popularne wzorce• Response service

– Komunikaty mogą być jednokierunkowe– Można zapisywać odpowiedzi w innej kolejce

• HTTP Bridge– Kolejki – raczej intranet– Nie interoperacyjne– Mostek WS-HTTP

Page 108: Windows Communication Foundation

Bezpieczeństwo(podstawy)

Page 109: Windows Communication Foundation

Tryby

• Transport – Negocjacja (protokół), zależy od protokołu– Weryfikacja integralności treści komunikatu – Akcelerowane przez karty sieciowe

• Message– Treść komunikatu szyfrowana

• Mieszane– Mix - transport do integralności i szyfrowanie

hasła– Oba – uwaga na wydajność

Page 110: Windows Communication Foundation

Bindingi i tryby bezpieczeństwa

Page 111: Windows Communication Foundation

Intranet• Bindingi

– NetTcpBinding– NetNamedPipeBinding– NetMsmqBinding

• Transport security– None– Signed – tożsamość nadawcy i integralność komunikatu– Encrypted and signed – dodatkowo szyfrowanie

• Najczęściej – uwierzytelnienie Windows (domain / username / password)• Autoryzacja – grupy Windows

<bindings> <netTcpBinding> <binding name = "TCPWindowsSecurity"> <security mode = "Transport"> <transport clientCredentialType = "Windows" protectionLevel = "EncryptAndSign" /> </security> </binding> </netTcpBinding></bindings>

Page 112: Windows Communication Foundation

Intranet – c.d.• ServiceSercurityContext.Current

– IsAnonymous– PrimaryIdentity– WindowsIdentity

• Thread.CurrentPrincipal : IPrincipal• PrincipalPermissionMode

– UseWindowsGroups– UseAspNetRoles– None, Custom

• Deklaratywne wymuszanie– [PrincipalPermission(SecurityAction.Demand, Role = „Manager”)]

• Impersonacja– Możliwa, ale niezalecana

Page 113: Windows Communication Foundation

Internet• Bindingi

– WSHttpBinding– WSDualHttpBinding

• Message security– Szyfrowanie certyfikatem X509

• Certyfikat– Plik konfiguracyjny (więcej kłopotu ze zmianami)– Trusted People – zalecane

• Tryb walidacji certyfikatu (certificateValidation)– PeerTrust – TrustedPeople– ChainTrust – zaufane root authority: Verisign / Thwart / …– PeerOrChainTrust

<behavior name = "Internet"><serviceCredentials>             

<serviceCertificate                findValue     = "MyServiceCert"                storeLocation = "LocalMachine"                storeName     = "My"                x509FindType  = "FindBySubjectName"             />          

</serviceCredentials>       

</behavior>

Page 114: Windows Communication Foundation

Uwierzytelnienie// Hasło (klasycznie)

MyContractClient proxy = new MyContractClient( );proxy.ClientCredentials.UserName.UserName = "MyUsername";proxy.ClientCredentials.UserName.Password = "MyPassword";proxy.MyMethod( );proxy.Close( );

// Windows (raczej nie stosowane w Internet, chociaż możliwe) <behavior name = "UsernameWindows"> <serviceCredentials> <userNameAuthentication userNamePasswordValidationMode = "Windows"/> <serviceCertificate . . . /> </serviceCredentials> </behavior>

Page 115: Windows Communication Foundation

Autoryzacja

• Najprościej – Role Provider– Model znany z ASP.NET– Dowolne źródło danych (własna lub generowana

baza)• Duplex

– Odradzane, w prosty sposób autoryzacja niedostępna

Page 116: Windows Communication Foundation

B2B

• Nie współdzielą kont– Przedstawianie się certyfikatem X509 (klient)– Dozwoleni klienci instalowani w Trusted People

• Szyfrowanie certyfikatem serwera• Najczęściej nie potrzebna autoryzacja

– Niewielka liczba lub jeden klient– Możliwe wykorzystanie Role Providera –

identyfikator certyfikatu jako username

Page 117: Windows Communication Foundation

Podsumowanie

Page 118: Windows Communication Foundation

Programowanie Web w WCF

REST, Get, Post, Delete,RSS (i HTTP)

Page 119: Windows Communication Foundation

Terminologia• RSS – prosty format XML dla zestawu danych• ATOM – jak RSS, ale bardziej ustrukturalizowany• Syndykacja (Syndication) – nadzbiór RSS, ATOM, inne• AJAX – DHTML + JavaScript + asynchroniczne

przetwarzanie• JSON – Format danych (tablicy) w JavaScript• REST – …• POX – plain old XML (bez koperty SOAP)

Page 120: Windows Communication Foundation

REST• Protokół HTTP został zaprojektowany z 8 słowami• Low REST – API bazujące na GET & POST

– Też tak działa przeglądarka

• High REST sugeruje stosowanie 4 głównych słow– GET/PUT/DELETE/POST– CRUD dla Web

• Wywoływanie usługi bez warstwy „komunikatu” czy „koperty”– …sam HTTP

• Oparte na– URI do definowania endpoint (zasób)

• Spacje & URITemplates

– Polecenia HTTP definiują operacje• GET/PUT/DELETE/POST

– Typy zawartości• XML , JSON, <mikroformaty>

Page 121: Windows Communication Foundation

Aplikacje REST - atrybuty• WebGet: Atrybut do oznaczania operacji które są

wołane przez HTTP GET• webHttpBinding: Binding dla usług REST• webServiceHost: Klasa do hostowania usług REST• webServiceHostFactory: Klasa do hostowania usług

REST które nie wymagają pliku konfiguracyjnego

[OperationContract][WebGet(UriTemplate=“/WeatherMap/{country}/{zipcode}”)]Stream GetWeatherMap(String country, String zipcode);

Page 122: Windows Communication Foundation

Developing REST ApplicationsWCF & URI Spaces: URITemplate

• QueryString syntax still available• URITemplate: formalism for binding URI structure to method

parameters

[OperationContract][WebGet(UriTemplate=“/WeatherMap/{country}/{zipcode}”)]Stream GetWeatherMap(String country, String zipcode);

http://myserver/WeatherMap/USA/98052

http://myserver/GetWeatherMap?country=USA&zipcode=98052

Page 123: Windows Communication Foundation

Developing REST ApplicationsWCF & Transfer: HTTP verbs support

• WebInvoke: new attribute for making a method accept any non-GET verb– PUT, DELETE, POST...

[OperationContract][WebInvoke(METHOD=“PUT”)]WeatherReport UploadWeatherReport(WeatherReport theReport);

Page 124: Windows Communication Foundation

Ręczne modelowanie URI• Pomoc: System.UriTemplate

Uri address = new Uri(“http://localhost:2000”);

UriTemplate template =

new UriTemplate(“{artist}/{album}”);

Uri boundUri =

template.BindByPosition(address,

“Northwind”, “Overdone”);

UriTemplateMatch match = template.Match(address,

boundUri);

String bandName = match.BoundVariables[“artist”];

Page 125: Windows Communication Foundation

URI w kontrakcie WCF

• Składnia QueryString nadal dostępna• Typ UriTemplate mapuje na parametry

– Jako atrybut albo jako oddzielny typ

[OperationContract][WebGet(UriTemplate=“/Image/{bandName}/{album}”)]Stream GetAlbumImage(String bandName, String album);

[OperationContract][WebGet(UriTemplate=“/Image?name={bandName})]Stream GetMainImage(String bandName);

Page 126: Windows Communication Foundation

Kontrakt typu zobacz / zrób

[OperationContract]

[WebGet(UriTemplate=“/Image/{bandName}/{album}”)]

Stream GetAlbumImage(String bandName, String album);

[OperationContract]

[WebInvoke(METHOD=“PUT”)] // {PUT, POST, DELETE}

void AddAlbum(AlbumInfo albumInfo);

Page 127: Windows Communication Foundation

REST – zwracanie wartości• Typ zawartości zależy od:

– Zachowanie enableWebScript (JSON) albo ustawione w klasie hostującej

– Atrybutu Response.Format– Ręcznie:

• WebOperationContext.Current.OutgoingResponse.ContentType

[OperationContract][WebGet(UriTemplate = "WeatherReport/{country}/{zipcode}/JSON",ResponseFormat=WebMessageFormat.Json)]WeatherReport GetWeatherReportWithTemplateJSON(string country, string zipcode);

Page 128: Windows Communication Foundation

JSON – co to jest?• JavaScript Object Notation• Format do łączenia JavaScript i obiektów

– Łatwiejsze niż XML

• Użycie– ASP.NET AJAX – Skrypty JS– Dynamiczny kod…

var data = {“temp” : 59, “descr” : “cloudy”};

document.write (“The weather is “ + data.descr);

Page 129: Windows Communication Foundation

Konwencje związane z danymi

[OperationContract(Name=“TestOp”)]

[WebInvoke(METHOD=“PUT”)] // {PUT, POST, DELETE}

String[] AddAlbum(AlbumInfo albumInfo);

PUT /albumservice/AddAlbum HTTP 1.1

HOST: contoso.com<albumInfo> <Name>Hysteria</Name> <RelDate>8/3/1987</RelDate> ...</albumInfo>

•XML Namespace pochodzi z kontraktu

•Nazwy parametrów z sygnatury operacji

Page 130: Windows Communication Foundation

Zwrócenie rysunku w WCF

Stream GetAlbumImage(String bandName, String album){ Stream stream; // obraz „skądś”

// ustawiamy ContentType i zwracamy strumień WebOperationContext.Current.OutgoingResponse.ContentType = “image/jpeg”; return stream;}

Page 131: Windows Communication Foundation

WCF i syndykacjaSyndykacja: Gromadzenie danych z różnych źródeł w jednym miejscu (blogi, artykuły itp.)SyndicationFeed: pojęcie „feedu” niezależne od formatuSyndicationFeedFormatter<>

[ServiceKnownType(typeof(Atom10FeedFormatter))]

[ServiceKnownType(typeof(Rss20FeedFormatter))]

[ServiceContract]

interface IPictureSyndication {

[OperationContract]

[WebGet(UriTemplate=“Images/{format}")]

SyndicationFeedFormatter<SyndicationFeed>

GetImage(String format);

}

Page 132: Windows Communication Foundation

Kontekst bez protokołu WS=*• Konwersacja bazująca na kanale komunikacyjnym - problem• Konwencja wywołania

– W tle

• Binding: basicHttpContextBindingNetTcpContextBindingBasicHttpContextBinding

• Behavior:– <persistenceProvider>

• Ten sam co w WF

• Uwaga! Klient musi też być świadomy kontekstu– WCF Service Host nie jest…