SlideShare uma empresa Scribd logo
1 de 132
Windows Communication
Foundation
Bartłomiej Zass
ISV Developer Evangelist
Microsoft
Od obiektów do usług
Polimorfizm
Hermetyzacja
Dziedziczenie
Komunikat
Schemat + kontrakt + polisa
Szeroka współpraca
Położenie dowolne
Ścisły związek
Metadane w czasie działania
Obiektowe UsługiKomponentowe
1980 20001990
Zadania serwera aplikacyjnego
• „Pojemnik” na obiekty realizujące daną funkcjonalnośd
– Jak pisad logikę obiektów?
• Infrastruktura: transakcje, sesje, stan…
• Mechanizmy komunikacji
• Skalowalnośd: 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ądzeo klienckich (za Wikipedia).
Komputer dedykowany do wykonania określonych
programów/zadao.
+ architektura
MTS
Komponenty
Runtime aplikacji
Deklaratywne transakcje
i bezpieczeostwo
Autoryzacja oparta o
role
COM+
Luźno powiązane zdarzenia
Komponentyu kolejkowane
„przepustnica” – nie więcej niż
x komponentów
Enterprise Services
Model programowania w kodzie
zarządzalnym
Oparty o atrybuty, deklaratywny,
konfiguracja w XML
Windows Communication
Foundation
• Komunikaty oparte o XML
• Dowolny transport
• Zorientowane na usługi
• Bezpieczeostwo: Federacja,
CardSpace (dowody tożsamości)
• Hosting - gdziekolwiek
Ewolucja usług aplikacyjnych
-2002 2002-2006 2006-
Problem – komunikacja…
4 podstawowe doktryny SOA
Wyraźne granice
Usługi są
autonomiczne
Usługi dzielą kontrakt
nie klasę
Kompatybilność
określana przez policy
Wprowadzenie do WCF
WCF: Adres, Binding, Kontrakt
Klient Usługa
KomunikatABC A B C
A B C
Adres Binding Kontrakt
(Gdzie) (Jak) (Co)
Endpoint
Endpoint
Endpoint
Encoder
Transport
BasicHttp, WSHttp,
WSDualHttp,
WSFederation
…Context…
NetTcp,
NetNamedPipe,
NetPeerTcp
NetMsmq,
MsmqIntegration
WCF – standardowe bindingi
Binding Interop Bezp. Sesja Trans. Duplex
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śd | B = Oba | RS = Pewna sesja
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
WCF na jednym slajdzie
Definicja „koocó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
Kontrakt
• Definiują funkcjonalnośd usługi.
• Atrybuty kontraktu:
– ServiceContract
• OperationContract
– DataContract
– FaultContract
– MessageContract
• MessageBody
• MessageHeader
• Zachowania kontraktu
– Sesja, transakcje, sposób inicjacji…
Kontrakt
• Możliwośd 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 = „…”)+
Host
• IIS + WAS (Vista+, Windows Server 2008+)
– Zarządzanie, skalowalnośd, 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
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
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" %>
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;
}
}
Bindingi
• Protokół (HTTP, TCP, IPC, MSMQ)
• Enkodowanie (plain text, MTOM)
• Bezpieczeostwo (transport, komunikat)
• …
Inne popularne bindingi
• NetPeerTcpBinding
• WSFederationHttpBinding
• WS2007FederationHttpBinding
• MsmqIntegrationBinding
• WebHttpBinding
• WS2007HttpBinding
Wybór bindingu
Endpoint
• „Koocówka”, z którą możemy się
komunikowad
– Przynajmniej jeden dla każdej usługi
• Dokładnie jeden kontrakt
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>
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>
Po stronie klienta
• Add service reference – automatycznie
• SvcUtil
SvcUtil http://localhost:8000/MEX /out:Proxy.cs
• WcfTestClient. exe http: //localhost:9000/
• Ręcznie - kod
public 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; }
//...
}
[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();
}
}
Wywoływanie usługi
MyContractClient proxy = new
MyContractClient("MyEndpoint");
proxy.MyMethod( );
proxy.Close( );
// Można również using…
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( );
}
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śd (domyślnie) i informowanie kiedy nie
dostarczono (ponawianie, itp.)
<binding name = "ReliableTCP">
<reliableSession enabled = "true"/>
</binding>
Kolejnośd komunikatów
• Nie powinniśmy wymagad konkretnego bindingu, ale czasem
istotna jest kolejnośd.
[DeliveryRequirements(TargetContract = typeof(IMyContract),
RequireOrderedDelivery = true) ]
class MyService : IMyContract, IMyOtherContract
{ ... }
[ServiceContract]
[DeliveryRequirements(RequireOrderedDelivery = true) ]
interface IMyContract { ... }
Kontrakt
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
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) ;
Zgodnośd 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;
}
Kontrakty danych
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 byd dostępna także po stronie klienta
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
Zdarzenia serializacji
• Np. inicjalizacja
• [OnSerializing], [OnSerialized]
[OnDeserializing], [OnDeserialized]
[DataContract]
class MyDataContract
{
[OnSerializing]
void OnSerializing(StreamingContext context) {. . .}
}
Inne
• Współdzielenie kontraktu
– Problem: ten sam typ w 2 serwisach (przestrzenie nazw)
– „Reuse types in reference assemblies”
• Dziedziczenie
– [KnownType], [ServiceKnownType]
// Customer : Contact
Contact contact = new Customer( );
ContactManagerClient proxy = new ContactManagerClient( );
// Błąd w czasie działania
proxy.AddContact(contact) ;
proxy.Close( );
// ------------------------
[DataContract]
[KnownType(typeof(Customer))]
class Contact { ... }
[DataContract]
class Customer : Contact { ... }
Współdzielenie kontraktu
• Zgodnośd 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;
}
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
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
Wersjonowanie kontraktu
• Dodawanie nowych pól
– Nadmiarowośd 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
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
Sposoby
instancjonowania
Kontekst
Zarządzanie kontekstem
• Tryby instancjonowania kontekstów
• Per Call
• Per Session
• Singleton
Per Call
• Bezstanowośd, skalowalnośd
– Konieczna inicjalizacja i zapis stanu
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class MyService : IMyContract
{ ... }
[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 = 1
MyService.Dispose( )
MyService.MyService( )
Counter = 1
MyService.Dispose( )
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śd na wyjściu
• Uwaga: Load Balancer i sesja
– Sticky Sessions
Per Session
• Domyślny tryb
• Instancja utrzymywana w pamięci
– Skalowalnośd
[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 {. . . }
Singleton
• Tworzony wraz ze startem procesu hosta
• Sesja nie wymagana
– Po zakooczeniu, nadal instancja w pamięci
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
class MyService : IMyContract { ... }
• Możliwe przekazanie zainicjalizowanej
instancji klasy do konstruktora hosta
Sesja a kontrakt
• Atrybuty gwarantujące prawidłową kolejnośd
wywołao
[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();
}
Zwalnianie kontekstu
• ReleaseInstanceMode.BeforeCall
• ReleaseInstanceMode.AfterCall
• ReleaseInstanceMode.BeforeAndAfterCall
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 kooczące (usunięcie instancji)
<behaviors>
<serviceBehaviors>
<behavior name = "DurableService">
<persistenceProvider
type = "... type ... , ... assembly ... "
<!-- Provider-specific parameters -->
/>
</behavior>
</serviceBehaviors>
</behaviors>
[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
}
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
Operacje
One-way
• [OperationContract(IsOneWay = true)]
– Przed metodą usługi
– Domyślnie – false
– Metoda musi zwracad 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
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();
}
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();
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)
Streaming
• Klasyczne wywołania – buforowane po stronie
serwera
– Blokowanie do czasu zakooczenia 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>
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);
}
Błędy
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( );
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;
}
}
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 byd w kontrakcie
• [FaultContract]
– Musi byd dokładnie klasa błędu
– Nie może byd to nawet klasa dziedzicząca!
– Może byd kilka – dla kilku typów
– Nie można aplikowad 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!
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 byd ustawiane ręcznie / w konfiguracji hosta (debugowanie istniejącego serwisu!)
// Uwaga przy deployment!
Transakcje
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
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>
Propagacja transakcji c.d.
• Nie wszystkie operacje muszą obsługiwad
transakcje
• [TransactionFlow]
– Allowed
– NotAllowed
– Mandatory
• Operacje OneWay – błąd
[ServiceContract]
interface IMyContract
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void MyMethod();
}
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
Transakcja z DTC
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);
}
}
Przykładowy przepływ
Głosowanie (commit)
• Deklaratywnie
– Zalecane
– domyślnie TransactionAutoComplete = true
– Jeśli mamy strukturę try-catch, wyrzucid wyjątek
dalej
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
public void MyMethod( )
{ ... }
[OperationBehavior(TransactionScopeRequired = true)]
public void MyMethod( )
{ ... }
Głosowanie (kod)
• Zatwierdzenie powinno byd 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;
}
}
Izolacja transakcji
• Domyślnie – Unspecified
– Wykorzystywany poziom transakcji klienta
• Jeśli inny – klient musi mied zadeklarowany
poziom transakcji taki sam (inaczej błąd)
class MyService : IMyContract
{ ... }
[ServiceBehavior(TransactionIsolationLevel =
IsolationLevel.Unspecified)]
class MyService : IMyContract
{ ... }
Klient
using (TransactionScope scope = new TransactionScope())
{
MyContractClient proxy1 = new MyContractClient( );
proxy1.MyMethod( );
proxy1.Close( );
MyOtherContractClient proxy2 = new MyOtherContractClient( );
proxy2.MyOtherMethod( );
proxy2.Close( );
scope.Complete( );
}
Instancjonowanie PerCall
MyContractClient proxy = new MyContractClient( );
using(TransactionScope scope = new TransactionScope( ))
{
proxy.MyMethod( ... ) ;
proxy.MyMethod( ... ) ;
scope.Complete( );
}
proxy.Close( );
Instancjonowanie PerSession
• Domyślnie – podobnie jak PerCall
– Po scope.Complete – instancja usuwana
– ReleaseServiceInstanceOnTransactionComplete
– ConcurrencyMode musi byd Single
[ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete = true)]
class MyService : IMyContract
{
[OperationBehavior(TransactionScopeRequired = true)]
public void MyMethod( )
{ ... }
[OperationBehavior( ... )]
public void MyOtherMethod( )
{ ... }
}
„Prawdziwe” PerSession
• ReleaseServiceInstanceOnTransactionComplete = false
• Zapisywanie stanu
– Resource Manager – jako klucz identyfikator sesji
OperationContext.Current.SessionId
– Volatile Resource Managers – pola obiektu instancji
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 {. . . }
Durable Services
• Stan zapisywany w bazie
– Transakcja może niechcący przed tym
powstrzymad
• Domyślnie – zapisywanie stanu nie jest
częścią transakcji
• [SaveStateInOperationTransaction]
– Domyślnie – false
– True – aby stan był zarządzany transakcją
Singleton
• Domyślnie – PerCall
– ReleaseServiceInstanceOnTransactionComplete
• Stan w Volatile Resource Managers
Wielowątkowośd
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łączeo
• Reentrant
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();
}
}
}
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();
}
}
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łao
http://msdn.microsoft.com/en-us/magazine/cc163321.aspx
Operacje asynchroniczne
• Specjalne pole checkbox podczas dodawania
referencji
• Klasycznie jak w .NET
– Begin<operacja>, End<operacja>
– End – blokuje
– Callback
– Polling – IsCompleted
– Wiele wywołao – WaitAll() i
IAsyncResult.WaitHandle
Serwisy kolejkowane
Serwisy kolejkowane
• Dostępnośd 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
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
Kolejkowanie w WCF
• Tylko operacje OneWay
– Nie mogą zwracad wartości
– Nie mogą zwracad 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"
... />
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
Sesja i MSMQ
• SessionMode.Allowed lub
SessionMode.NotAllowed – brak sesji
– Każdy komunikat pojedynczo
• SessionMode.Required
– Sessiongram – pakowanie komunikatów w
„paczkę”
– Zachowana kolejnośd doręczenia
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
Instancjonowanie PerSession
using(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
Instancjonowanie PerSession
• Nie mogą mied trwającej sesji
– Podobnie do PerCall
• Ale - wszystkie komunikaty do tej samej
instancji
Throttling
• Po włączeniu usługi – wszystkie komunikaty
na raz
– Duża liczba instancji kontekstu – obciążenie
• Umożliwia stopniowe przetwarzanie
Kiedy pojawią się problemy
• Błędy
– Komunikacja
– Bezpieczeostwo
– Quota
– …
• Dead-letter queue (DLQ)
– Problem z doręczeniem
– Nieudany commit transakcji playback
– Przetwarzanie kolejki jak zwykły serwis (kontrakt musi byd
ten sam / dziedziczący)
<! -- 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>
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
Popularne wzorce
• Response service
– Komunikaty mogą byd jednokierunkowe
– Można zapisywad odpowiedzi w innej kolejce
• HTTP Bridge
– Kolejki – raczej intranet
– Nie interoperacyjne
– Mostek WS-HTTP
Bezpieczeostwo
(podstawy)
Tryby
• Transport
– Negocjacja (protokół), zależy od protokołu
– Weryfikacja integralności treści komunikatu
– Akcelerowane przez karty sieciowe
• Message
– Treśd komunikatu szyfrowana
• Mieszane
– Mix - transport do integralności i szyfrowanie
hasła
– Oba – uwaga na wydajnośd
Bindingi i tryby bezpieczeostwa
Intranet
• Bindingi
– NetTcpBinding
– NetNamedPipeBinding
– NetMsmqBinding
• Transport security
– None
– Signed – tożsamośd nadawcy i integralnośd 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>
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
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>
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>
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
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
Podsumowanie
Programowanie Web w
WCF
REST, Get, Post, Delete,RSS (i HTTP)
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)
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>
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);
Developing REST Applications
WCF & 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
Developing REST Applications
WCF & 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);
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”];
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);
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);
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.Conte
ntType
[OperationContract]
[WebGet(UriTemplate =
"WeatherReport/{country}/{zipcode}/JSON",
ResponseFormat=WebMessageFormat.Json)]
WeatherReport GetWeatherReportWithTemplateJSON(string
country, string zipcode);
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);
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
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;
}
WCF i syndykacja
Syndykacja: Gromadzenie danych z różnych źródeł w
jednym miejscu (blogi, artykuły itp.)
SyndicationFeed: pojęcie „feedu” niezależne od
formatu
SyndicationFeedFormatter<>
[ServiceKnownType(typeof(Atom10FeedFormatter))]
[ServiceKnownType(typeof(Rss20FeedFormatter))]
[ServiceContract]
interface IPictureSyndication {
[OperationContract]
[WebGet(UriTemplate=“Images/{format}")]
SyndicationFeedFormatter<SyndicationFeed>
GetImage(String format);
}
Kontekst bez protokołu WS=*
• Konwersacja bazująca na kanale komunikacyjnym -
problem
• Konwencja wywołania
– W tle
• Binding:
basicHttpContextBinding
NetTcpContextBinding
BasicHttpContextBinding
• Behavior:
– <persistenceProvider>
• Ten sam co w WF 
• Uwaga! Klient musi też byd świadomy kontekstu
– WCF Service Host nie jest…

Mais conteúdo relacionado

Semelhante a Windows Communication Foundation

Azure Event Hubs - wprowadzenie
Azure Event Hubs - wprowadzenieAzure Event Hubs - wprowadzenie
Azure Event Hubs - wprowadzenieŁukasz Bargieł
 
Jak przerobić monolityczną aplikację na architekturę mikro serwisów ?
Jak przerobić monolityczną aplikację na architekturę mikro serwisów ?Jak przerobić monolityczną aplikację na architekturę mikro serwisów ?
Jak przerobić monolityczną aplikację na architekturę mikro serwisów ?Tomasz Lelek
 
Drobne błędy w portalach WWW -- prawdziwe studium przypadku
Drobne błędy w portalach WWW -- prawdziwe studium przypadkuDrobne błędy w portalach WWW -- prawdziwe studium przypadku
Drobne błędy w portalach WWW -- prawdziwe studium przypadkuLogicaltrust pl
 
Drobne błędy w portalach WWW -- prawdziwe studium przypadku
Drobne błędy w portalach WWW -- prawdziwe studium przypadkuDrobne błędy w portalach WWW -- prawdziwe studium przypadku
Drobne błędy w portalach WWW -- prawdziwe studium przypadkuLogicaltrust pl
 
Cloud computing na bazie Windows Azure, Tomek Kopacz, Microsoft
Cloud computing na bazie Windows Azure, Tomek Kopacz, MicrosoftCloud computing na bazie Windows Azure, Tomek Kopacz, Microsoft
Cloud computing na bazie Windows Azure, Tomek Kopacz, MicrosoftBiznes 2.0
 
Tomasz Kopacz, Cloud computing na bazie Windows Azure
Tomasz Kopacz, Cloud computing na bazie Windows AzureTomasz Kopacz, Cloud computing na bazie Windows Azure
Tomasz Kopacz, Cloud computing na bazie Windows AzureWebhosting.pl
 
Michał Dec - Quality in Clouds
Michał Dec - Quality in CloudsMichał Dec - Quality in Clouds
Michał Dec - Quality in Cloudskraqa
 
Aplikacje internetowe (2010)
Aplikacje internetowe (2010)Aplikacje internetowe (2010)
Aplikacje internetowe (2010)Adrian Kalbarczyk
 
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...Future Processing
 
Advanced Crypto Service Provider – kryptografia jako usługa
Advanced Crypto Service Provider – kryptografia jako usługaAdvanced Crypto Service Provider – kryptografia jako usługa
Advanced Crypto Service Provider – kryptografia jako usługaSmart Coders
 
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacji
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacjiProjektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacji
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacjiAntoni Orfin
 
PLNOG 8: Tomaz Kozar - UCaaS jako usługa z chmury
PLNOG 8: Tomaz Kozar - UCaaS jako usługa z chmury PLNOG 8: Tomaz Kozar - UCaaS jako usługa z chmury
PLNOG 8: Tomaz Kozar - UCaaS jako usługa z chmury PROIDEA
 
Citrix provisioning services
Citrix provisioning servicesCitrix provisioning services
Citrix provisioning servicesPawel Serwan
 
Space Wars Hack - Class #1
Space Wars Hack - Class #1Space Wars Hack - Class #1
Space Wars Hack - Class #1Piotr Pawlak
 
Wprowadzenie do Cloud OS
Wprowadzenie do Cloud OSWprowadzenie do Cloud OS
Wprowadzenie do Cloud OSLukasz Kaluzny
 
Przetwarzanie asynchroniczne w zastosowaniach webowych
Przetwarzanie asynchroniczne w zastosowaniach webowychPrzetwarzanie asynchroniczne w zastosowaniach webowych
Przetwarzanie asynchroniczne w zastosowaniach webowychleafnode
 
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?The Software House
 
Asynchroniczny PHP i komunikacja czasu rzeczywistego z wykorzystaniem websocketw
Asynchroniczny PHP i komunikacja czasu rzeczywistego z wykorzystaniem websocketwAsynchroniczny PHP i komunikacja czasu rzeczywistego z wykorzystaniem websocketw
Asynchroniczny PHP i komunikacja czasu rzeczywistego z wykorzystaniem websocketwLuke Adamczewski
 
Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websock...
Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websock...Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websock...
Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websock...Polcode
 

Semelhante a Windows Communication Foundation (20)

Azure Event Hubs - wprowadzenie
Azure Event Hubs - wprowadzenieAzure Event Hubs - wprowadzenie
Azure Event Hubs - wprowadzenie
 
Jak przerobić monolityczną aplikację na architekturę mikro serwisów ?
Jak przerobić monolityczną aplikację na architekturę mikro serwisów ?Jak przerobić monolityczną aplikację na architekturę mikro serwisów ?
Jak przerobić monolityczną aplikację na architekturę mikro serwisów ?
 
Drobne błędy w portalach WWW -- prawdziwe studium przypadku
Drobne błędy w portalach WWW -- prawdziwe studium przypadkuDrobne błędy w portalach WWW -- prawdziwe studium przypadku
Drobne błędy w portalach WWW -- prawdziwe studium przypadku
 
Drobne błędy w portalach WWW -- prawdziwe studium przypadku
Drobne błędy w portalach WWW -- prawdziwe studium przypadkuDrobne błędy w portalach WWW -- prawdziwe studium przypadku
Drobne błędy w portalach WWW -- prawdziwe studium przypadku
 
Cloud computing na bazie Windows Azure, Tomek Kopacz, Microsoft
Cloud computing na bazie Windows Azure, Tomek Kopacz, MicrosoftCloud computing na bazie Windows Azure, Tomek Kopacz, Microsoft
Cloud computing na bazie Windows Azure, Tomek Kopacz, Microsoft
 
Tomasz Kopacz, Cloud computing na bazie Windows Azure
Tomasz Kopacz, Cloud computing na bazie Windows AzureTomasz Kopacz, Cloud computing na bazie Windows Azure
Tomasz Kopacz, Cloud computing na bazie Windows Azure
 
Michał Dec - Quality in Clouds
Michał Dec - Quality in CloudsMichał Dec - Quality in Clouds
Michał Dec - Quality in Clouds
 
Aplikacje internetowe (2010)
Aplikacje internetowe (2010)Aplikacje internetowe (2010)
Aplikacje internetowe (2010)
 
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...
[JuraSIC! Meetup] Krzysztof Sikora- Jak Service Fabric rozwiąże twoje problem...
 
Advanced Crypto Service Provider – kryptografia jako usługa
Advanced Crypto Service Provider – kryptografia jako usługaAdvanced Crypto Service Provider – kryptografia jako usługa
Advanced Crypto Service Provider – kryptografia jako usługa
 
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacji
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacjiProjektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacji
Projektowanie wysokowydajnych i skalowalnych serwisów WWW - Warstwa aplikacji
 
PLNOG 8: Tomaz Kozar - UCaaS jako usługa z chmury
PLNOG 8: Tomaz Kozar - UCaaS jako usługa z chmury PLNOG 8: Tomaz Kozar - UCaaS jako usługa z chmury
PLNOG 8: Tomaz Kozar - UCaaS jako usługa z chmury
 
Citrix provisioning services
Citrix provisioning servicesCitrix provisioning services
Citrix provisioning services
 
Space Wars Hack - Class #1
Space Wars Hack - Class #1Space Wars Hack - Class #1
Space Wars Hack - Class #1
 
Wprowadzenie do Cloud OS
Wprowadzenie do Cloud OSWprowadzenie do Cloud OS
Wprowadzenie do Cloud OS
 
Przetwarzanie asynchroniczne w zastosowaniach webowych
Przetwarzanie asynchroniczne w zastosowaniach webowychPrzetwarzanie asynchroniczne w zastosowaniach webowych
Przetwarzanie asynchroniczne w zastosowaniach webowych
 
Torquebox
TorqueboxTorquebox
Torquebox
 
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
Monitoring systemu. Dlaczego mój kardiolog jest bogatym człowiekiem?
 
Asynchroniczny PHP i komunikacja czasu rzeczywistego z wykorzystaniem websocketw
Asynchroniczny PHP i komunikacja czasu rzeczywistego z wykorzystaniem websocketwAsynchroniczny PHP i komunikacja czasu rzeczywistego z wykorzystaniem websocketw
Asynchroniczny PHP i komunikacja czasu rzeczywistego z wykorzystaniem websocketw
 
Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websock...
Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websock...Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websock...
Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websock...
 

Windows Communication Foundation

  • 2. Od obiektów do usług Polimorfizm Hermetyzacja Dziedziczenie Komunikat Schemat + kontrakt + polisa Szeroka współpraca Położenie dowolne Ścisły związek Metadane w czasie działania Obiektowe UsługiKomponentowe 1980 20001990
  • 3. Zadania serwera aplikacyjnego • „Pojemnik” na obiekty realizujące daną funkcjonalnośd – Jak pisad logikę obiektów? • Infrastruktura: transakcje, sesje, stan… • Mechanizmy komunikacji • Skalowalnośd: 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ądzeo klienckich (za Wikipedia). Komputer dedykowany do wykonania określonych programów/zadao. + architektura
  • 4. MTS Komponenty Runtime aplikacji Deklaratywne transakcje i bezpieczeostwo Autoryzacja oparta o role COM+ Luźno powiązane zdarzenia Komponentyu kolejkowane „przepustnica” – nie więcej niż x komponentów Enterprise Services Model programowania w kodzie zarządzalnym Oparty o atrybuty, deklaratywny, konfiguracja w XML Windows Communication Foundation • Komunikaty oparte o XML • Dowolny transport • Zorientowane na usługi • Bezpieczeostwo: Federacja, CardSpace (dowody tożsamości) • Hosting - gdziekolwiek Ewolucja usług aplikacyjnych
  • 5. -2002 2002-2006 2006- Problem – komunikacja…
  • 6. 4 podstawowe doktryny SOA Wyraźne granice Usługi są autonomiczne Usługi dzielą kontrakt nie klasę Kompatybilność określana przez policy
  • 8. WCF: Adres, Binding, Kontrakt Klient Usługa KomunikatABC A B C A B C Adres Binding Kontrakt (Gdzie) (Jak) (Co) Endpoint Endpoint Endpoint Encoder Transport BasicHttp, WSHttp, WSDualHttp, WSFederation …Context… NetTcp, NetNamedPipe, NetPeerTcp NetMsmq, MsmqIntegration
  • 9. WCF – standardowe bindingi Binding Interop Bezp. Sesja Trans. Duplex 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śd | B = Oba | RS = Pewna sesja
  • 10. 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
  • 11. WCF na jednym slajdzie Definicja „koocó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
  • 12. Kontrakt • Definiują funkcjonalnośd usługi. • Atrybuty kontraktu: – ServiceContract • OperationContract – DataContract – FaultContract – MessageContract • MessageBody • MessageHeader • Zachowania kontraktu – Sesja, transakcje, sposób inicjacji…
  • 13. Kontrakt • Możliwośd 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 = „…”)+
  • 14. Host • IIS + WAS (Vista+, Windows Server 2008+) – Zarządzanie, skalowalnośd, 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
  • 15. 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
  • 16. 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" %>
  • 17. 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; } }
  • 18. Bindingi • Protokół (HTTP, TCP, IPC, MSMQ) • Enkodowanie (plain text, MTOM) • Bezpieczeostwo (transport, komunikat) • …
  • 19. Inne popularne bindingi • NetPeerTcpBinding • WSFederationHttpBinding • WS2007FederationHttpBinding • MsmqIntegrationBinding • WebHttpBinding • WS2007HttpBinding
  • 21. Endpoint • „Koocówka”, z którą możemy się komunikowad – Przynajmniej jeden dla każdej usługi • Dokładnie jeden kontrakt
  • 22. 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>
  • 23. 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>
  • 24. Po stronie klienta • Add service reference – automatycznie • SvcUtil SvcUtil http://localhost:8000/MEX /out:Proxy.cs • WcfTestClient. exe http: //localhost:9000/ • Ręcznie - kod public 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; } //... }
  • 25. [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(); } }
  • 26. Wywoływanie usługi MyContractClient proxy = new MyContractClient("MyEndpoint"); proxy.MyMethod( ); proxy.Close( ); // Można również using…
  • 27. 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( ); }
  • 28. 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śd (domyślnie) i informowanie kiedy nie dostarczono (ponawianie, itp.) <binding name = "ReliableTCP"> <reliableSession enabled = "true"/> </binding>
  • 29. Kolejnośd komunikatów • Nie powinniśmy wymagad konkretnego bindingu, ale czasem istotna jest kolejnośd. [DeliveryRequirements(TargetContract = typeof(IMyContract), RequireOrderedDelivery = true) ] class MyService : IMyContract, IMyOtherContract { ... } [ServiceContract] [DeliveryRequirements(RequireOrderedDelivery = true) ] interface IMyContract { ... }
  • 31. 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
  • 32. 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) ;
  • 33. Zgodnośd 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; }
  • 35. 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 byd dostępna także po stronie klienta
  • 36. 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
  • 37. Zdarzenia serializacji • Np. inicjalizacja • [OnSerializing], [OnSerialized] [OnDeserializing], [OnDeserialized] [DataContract] class MyDataContract { [OnSerializing] void OnSerializing(StreamingContext context) {. . .} }
  • 38. Inne • Współdzielenie kontraktu – Problem: ten sam typ w 2 serwisach (przestrzenie nazw) – „Reuse types in reference assemblies” • Dziedziczenie – [KnownType], [ServiceKnownType] // Customer : Contact Contact contact = new Customer( ); ContactManagerClient proxy = new ContactManagerClient( ); // Błąd w czasie działania proxy.AddContact(contact) ; proxy.Close( ); // ------------------------ [DataContract] [KnownType(typeof(Customer))] class Contact { ... } [DataContract] class Customer : Contact { ... }
  • 39. Współdzielenie kontraktu • Zgodnośd 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; }
  • 40. 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
  • 41. 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
  • 42. Wersjonowanie kontraktu • Dodawanie nowych pól – Nadmiarowośd 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
  • 43. 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
  • 46. Zarządzanie kontekstem • Tryby instancjonowania kontekstów • Per Call • Per Session • Singleton
  • 47. Per Call • Bezstanowośd, skalowalnośd – Konieczna inicjalizacja i zapis stanu [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] class MyService : IMyContract { ... }
  • 48. [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 = 1 MyService.Dispose( ) MyService.MyService( ) Counter = 1 MyService.Dispose( )
  • 49. 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śd na wyjściu • Uwaga: Load Balancer i sesja – Sticky Sessions
  • 50. Per Session • Domyślny tryb • Instancja utrzymywana w pamięci – Skalowalnośd [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 {. . . }
  • 51. Singleton • Tworzony wraz ze startem procesu hosta • Sesja nie wymagana – Po zakooczeniu, nadal instancja w pamięci [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] class MyService : IMyContract { ... } • Możliwe przekazanie zainicjalizowanej instancji klasy do konstruktora hosta
  • 52. Sesja a kontrakt • Atrybuty gwarantujące prawidłową kolejnośd wywołao [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(); }
  • 53. Zwalnianie kontekstu • ReleaseInstanceMode.BeforeCall • ReleaseInstanceMode.AfterCall • ReleaseInstanceMode.BeforeAndAfterCall
  • 54. 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 kooczące (usunięcie instancji) <behaviors> <serviceBehaviors> <behavior name = "DurableService"> <persistenceProvider type = "... type ... , ... assembly ... " <!-- Provider-specific parameters --> /> </behavior> </serviceBehaviors> </behaviors>
  • 55. [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 }
  • 56. 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
  • 58. One-way • [OperationContract(IsOneWay = true)] – Przed metodą usługi – Domyślnie – false – Metoda musi zwracad 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
  • 59. 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(); }
  • 60. 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();
  • 61. 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)
  • 62. Streaming • Klasyczne wywołania – buforowane po stronie serwera – Blokowanie do czasu zakooczenia 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>
  • 63. 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); }
  • 65. 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( );
  • 66. 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; } }
  • 67. 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 byd w kontrakcie • [FaultContract] – Musi byd dokładnie klasa błędu – Nie może byd to nawet klasa dziedzicząca! – Może byd kilka – dla kilku typów – Nie można aplikowad 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!
  • 68. 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 byd ustawiane ręcznie / w konfiguracji hosta (debugowanie istniejącego serwisu!) // Uwaga przy deployment!
  • 70. 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
  • 71. 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>
  • 72. Propagacja transakcji c.d. • Nie wszystkie operacje muszą obsługiwad transakcje • [TransactionFlow] – Allowed – NotAllowed – Mandatory • Operacje OneWay – błąd [ServiceContract] interface IMyContract { [OperationContract] [TransactionFlow(TransactionFlowOption.Allowed)] void MyMethod(); }
  • 73. 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
  • 75. 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); } }
  • 77. Głosowanie (commit) • Deklaratywnie – Zalecane – domyślnie TransactionAutoComplete = true – Jeśli mamy strukturę try-catch, wyrzucid wyjątek dalej [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] public void MyMethod( ) { ... } [OperationBehavior(TransactionScopeRequired = true)] public void MyMethod( ) { ... }
  • 78. Głosowanie (kod) • Zatwierdzenie powinno byd 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; } }
  • 79. Izolacja transakcji • Domyślnie – Unspecified – Wykorzystywany poziom transakcji klienta • Jeśli inny – klient musi mied zadeklarowany poziom transakcji taki sam (inaczej błąd) class MyService : IMyContract { ... } [ServiceBehavior(TransactionIsolationLevel = IsolationLevel.Unspecified)] class MyService : IMyContract { ... }
  • 80. Klient using (TransactionScope scope = new TransactionScope()) { MyContractClient proxy1 = new MyContractClient( ); proxy1.MyMethod( ); proxy1.Close( ); MyOtherContractClient proxy2 = new MyOtherContractClient( ); proxy2.MyOtherMethod( ); proxy2.Close( ); scope.Complete( ); }
  • 81. Instancjonowanie PerCall MyContractClient proxy = new MyContractClient( ); using(TransactionScope scope = new TransactionScope( )) { proxy.MyMethod( ... ) ; proxy.MyMethod( ... ) ; scope.Complete( ); } proxy.Close( );
  • 82. Instancjonowanie PerSession • Domyślnie – podobnie jak PerCall – Po scope.Complete – instancja usuwana – ReleaseServiceInstanceOnTransactionComplete – ConcurrencyMode musi byd Single [ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete = true)] class MyService : IMyContract { [OperationBehavior(TransactionScopeRequired = true)] public void MyMethod( ) { ... } [OperationBehavior( ... )] public void MyOtherMethod( ) { ... } }
  • 83. „Prawdziwe” PerSession • ReleaseServiceInstanceOnTransactionComplete = false • Zapisywanie stanu – Resource Manager – jako klucz identyfikator sesji OperationContext.Current.SessionId – Volatile Resource Managers – pola obiektu instancji
  • 84. 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 {. . . }
  • 85. Durable Services • Stan zapisywany w bazie – Transakcja może niechcący przed tym powstrzymad • Domyślnie – zapisywanie stanu nie jest częścią transakcji • [SaveStateInOperationTransaction] – Domyślnie – false – True – aby stan był zarządzany transakcją
  • 86. Singleton • Domyślnie – PerCall – ReleaseServiceInstanceOnTransactionComplete • Stan w Volatile Resource Managers
  • 88. 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łączeo • Reentrant
  • 89. 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(); } } }
  • 90. 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(); } }
  • 91. 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łao http://msdn.microsoft.com/en-us/magazine/cc163321.aspx
  • 92. Operacje asynchroniczne • Specjalne pole checkbox podczas dodawania referencji • Klasycznie jak w .NET – Begin<operacja>, End<operacja> – End – blokuje – Callback – Polling – IsCompleted – Wiele wywołao – WaitAll() i IAsyncResult.WaitHandle
  • 94. Serwisy kolejkowane • Dostępnośd 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
  • 95. 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
  • 96. Kolejkowanie w WCF • Tylko operacje OneWay – Nie mogą zwracad wartości – Nie mogą zwracad 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" ... />
  • 97. 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
  • 98. Sesja i MSMQ • SessionMode.Allowed lub SessionMode.NotAllowed – brak sesji – Każdy komunikat pojedynczo • SessionMode.Required – Sessiongram – pakowanie komunikatów w „paczkę” – Zachowana kolejnośd doręczenia
  • 99. 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
  • 100. Instancjonowanie PerSession using(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
  • 101. Instancjonowanie PerSession • Nie mogą mied trwającej sesji – Podobnie do PerCall • Ale - wszystkie komunikaty do tej samej instancji
  • 102. Throttling • Po włączeniu usługi – wszystkie komunikaty na raz – Duża liczba instancji kontekstu – obciążenie • Umożliwia stopniowe przetwarzanie
  • 103. Kiedy pojawią się problemy • Błędy – Komunikacja – Bezpieczeostwo – Quota – … • Dead-letter queue (DLQ) – Problem z doręczeniem – Nieudany commit transakcji playback – Przetwarzanie kolejki jak zwykły serwis (kontrakt musi byd ten sam / dziedziczący)
  • 104. <! -- 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>
  • 105. 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
  • 106.
  • 107. Popularne wzorce • Response service – Komunikaty mogą byd jednokierunkowe – Można zapisywad odpowiedzi w innej kolejce • HTTP Bridge – Kolejki – raczej intranet – Nie interoperacyjne – Mostek WS-HTTP
  • 109. Tryby • Transport – Negocjacja (protokół), zależy od protokołu – Weryfikacja integralności treści komunikatu – Akcelerowane przez karty sieciowe • Message – Treśd komunikatu szyfrowana • Mieszane – Mix - transport do integralności i szyfrowanie hasła – Oba – uwaga na wydajnośd
  • 110. Bindingi i tryby bezpieczeostwa
  • 111. Intranet • Bindingi – NetTcpBinding – NetNamedPipeBinding – NetMsmqBinding • Transport security – None – Signed – tożsamośd nadawcy i integralnośd 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>
  • 112. 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
  • 113. 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>
  • 114. 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>
  • 115. 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
  • 116. 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
  • 118. Programowanie Web w WCF REST, Get, Post, Delete,RSS (i HTTP)
  • 119. 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)
  • 120. 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>
  • 121. 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);
  • 122. Developing REST Applications WCF & 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
  • 123. Developing REST Applications WCF & 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);
  • 124. 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”];
  • 125. 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);
  • 126. 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);
  • 127. 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.Conte ntType [OperationContract] [WebGet(UriTemplate = "WeatherReport/{country}/{zipcode}/JSON", ResponseFormat=WebMessageFormat.Json)] WeatherReport GetWeatherReportWithTemplateJSON(string country, string zipcode);
  • 128. 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);
  • 129. 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
  • 130. 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; }
  • 131. WCF i syndykacja Syndykacja: Gromadzenie danych z różnych źródeł w jednym miejscu (blogi, artykuły itp.) SyndicationFeed: pojęcie „feedu” niezależne od formatu SyndicationFeedFormatter<> [ServiceKnownType(typeof(Atom10FeedFormatter))] [ServiceKnownType(typeof(Rss20FeedFormatter))] [ServiceContract] interface IPictureSyndication { [OperationContract] [WebGet(UriTemplate=“Images/{format}")] SyndicationFeedFormatter<SyndicationFeed> GetImage(String format); }
  • 132. Kontekst bez protokołu WS=* • Konwersacja bazująca na kanale komunikacyjnym - problem • Konwencja wywołania – W tle • Binding: basicHttpContextBinding NetTcpContextBinding BasicHttpContextBinding • Behavior: – <persistenceProvider> • Ten sam co w WF  • Uwaga! Klient musi też byd świadomy kontekstu – WCF Service Host nie jest…