Projektowanie kontraktów usług
W tym temacie opisano, jakie kontrakty usług są zdefiniowane, jakie operacje są dostępne (oraz implikacje dla bazowych wymian komunikatów), jakie typy danych są używane, oraz inne problemy, które ułatwiają projektowanie operacji spełniających wymagania scenariusza.
Tworzenie kontraktu usługi
Usługi uwidaczniają szereg operacji. W aplikacjach programu Windows Communication Foundation (WCF) zdefiniuj operacje, tworząc metodę i oznaczając ją za pomocą atrybutu OperationContractAttribute . Następnie, aby utworzyć kontrakt usługi, pogrupuj operacje, deklarując je w interfejsie oznaczonym atrybutem ServiceContractAttribute lub definiując je w klasie oznaczonej tym samym atrybutem. (Aby zapoznać się z podstawowym przykładem, zobacz Instrukcje: definiowanie kontraktu usługi).
Wszystkie metody, które nie mają atrybutu OperationContractAttribute , nie są operacjami usług i nie są uwidocznione przez usługi WCF.
W tym temacie opisano następujące kwestie decyzyjne podczas projektowania kontraktu usługi:
Czy używać klas, czy interfejsów.
Jak określić typy danych, które chcesz wymienić.
Typy wzorców wymiany, których można użyć.
Określa, czy można jawnie określić wymagania dotyczące zabezpieczeń w ramach umowy.
Ograniczenia dotyczące danych wejściowych i wyjściowych operacji.
Klasy lub interfejsy
Zarówno klasy, jak i interfejsy reprezentują grupowanie funkcji, a zatem oba te klasy mogą służyć do definiowania kontraktu usługi WCF. Zaleca się jednak używanie interfejsów, ponieważ bezpośrednio modelują kontrakty usług. Bez implementacji interfejsy nie definiują więcej niż grupowanie metod z określonymi podpisami. Zaimplementuj interfejs kontraktu usługi i zaimplementowano usługę WCF.
Wszystkie zalety interfejsów zarządzanych mają zastosowanie do interfejsów kontraktów usług:
Interfejsy kontraktów usług mogą rozszerzać dowolną liczbę innych interfejsów kontraktów usług.
Pojedyncza klasa może implementować dowolną liczbę kontraktów usług, implementując te interfejsy kontraktów usług.
Implementację kontraktu usługi można zmodyfikować, zmieniając implementację interfejsu, a kontrakt usługi pozostaje taki sam.
Możesz wersję usługi, implementując stary interfejs i nowy. Starzy klienci łączą się z oryginalną wersją, podczas gdy nowsi klienci mogą łączyć się z nowszą wersją.
Uwaga
Podczas dziedziczenia z innych interfejsów kontraktu usługi nie można zastąpić właściwości operacji, takich jak nazwa lub przestrzeń nazw. Jeśli spróbujesz to zrobić, utworzysz nową operację w bieżącym kontrakcie usługi.
Przykład użycia interfejsu do utworzenia kontraktu usługi można znaleźć w temacie How to: Create a Service with a Contract Interface (Jak utworzyć usługę za pomocą interfejsu kontraktu).
Można jednak użyć klasy do zdefiniowania kontraktu usługi i zaimplementowania tego kontraktu w tym samym czasie. Zaletą tworzenia usług przez zastosowanie ServiceContractAttribute i OperationContractAttribute bezpośrednio do klasy i metod odpowiednio w klasie i metod w klasie jest szybkość i prostota. Wadą jest to, że klasy zarządzane nie obsługują wielu dziedziczenia, a w rezultacie mogą implementować tylko jeden kontrakt usługi naraz. Ponadto wszelkie modyfikacje sygnatur klasy lub metody modyfikują kontrakt publiczny dla tej usługi, co może uniemożliwić niezmodyfikowanym klientom korzystanie z usługi. Aby uzyskać więcej informacji, zobacz Implementowanie kontraktów usług.
Przykład, który używa klasy do tworzenia kontraktu usługi i implementowania go w tym samym czasie, zobacz How to: Create a Service with a Contract Class (Jak utworzyć usługę z klasą kontraktu).
W tym momencie należy zrozumieć różnicę między definiowaniem kontraktu usługi przy użyciu interfejsu a użyciem klasy. Następnym krokiem jest podjęcie decyzji o tym, jakie dane mogą być przekazywane między usługą a jej klientami.
Parametry i wartości zwracane
Każda operacja ma wartość zwracaną i parametr, nawet jeśli są to void
. Jednak w przeciwieństwie do metody lokalnej, w której można przekazywać odwołania do obiektów z jednego obiektu do innego, operacje usługi nie przekazują odwołań do obiektów. Zamiast tego przekazują kopie obiektów.
Jest to istotne, ponieważ każdy typ używany w parametrze lub zwracanej wartości musi być serializowalny; oznacza to, że należy przekonwertować obiekt tego typu na strumień bajtów i ze strumienia bajtów do obiektu.
Typy pierwotne są domyślnie serializowalne, podobnie jak wiele typów w programie .NET Framework.
Uwaga
Wartość nazw parametrów w podpisie operacji jest częścią kontraktu i uwzględnia wielkość liter. Jeśli chcesz użyć tej samej nazwy parametru lokalnie, ale zmodyfikować nazwę w opublikowanych metadanych, zobacz System.ServiceModel.MessageParameterAttribute.
Kontrakty danych
Aplikacje zorientowane na usługi, takie jak aplikacje programu Windows Communication Foundation (WCF), są przeznaczone do współdziałania z największą liczbą aplikacji klienckich zarówno na platformach firmy Microsoft, jak i innych niż Microsoft. W przypadku najszerszego możliwego współdziałania zaleca się oznaczenie typów za pomocą DataContractAttribute atrybutów i DataMemberAttribute w celu utworzenia kontraktu danych, który jest częścią kontraktu usługi opisującego dane wymieniane przez operacje usługi.
Kontrakty danych są kontraktami w stylu zgody: żaden typ lub składowa danych nie jest serializowany, chyba że jawnie zastosujesz atrybut kontraktu danych. Kontrakty danych nie są powiązane z zakresem dostępu kodu zarządzanego: prywatne elementy członkowskie danych mogą być serializowane i wysyłane w innym miejscu, aby uzyskać dostęp publicznie. (Aby zapoznać się z podstawowym przykładem kontraktu danych, zobacz Instrukcje: tworzenie podstawowego kontraktu danych dla klasy lub struktury). Program WCF obsługuje definicję podstawowych komunikatów PROTOKOŁU SOAP, które umożliwiają działanie operacji, a także serializację typów danych do i z treści komunikatów. Tak długo, jak typy danych można serializować, nie trzeba myśleć o podstawowej infrastrukturze wymiany komunikatów podczas projektowania operacji.
Chociaż typowa aplikacja WCF używa DataContractAttribute atrybutów i DataMemberAttribute do tworzenia kontraktów danych dla operacji, można użyć innych mechanizmów serializacji. ISerializableStandard , SerializableAttributei IXmlSerializable mechanizmy działają tak, aby obsługiwać serializacji typów danych do bazowych komunikatów PROTOKOŁU SOAP, które przenoszą je z jednej aplikacji do innej. Można stosować więcej strategii serializacji, jeśli typy danych wymagają specjalnej obsługi. Aby uzyskać więcej informacji na temat opcji serializacji typów danych w aplikacjach WCF, zobacz Określanie transferu danych w kontraktach usług.
Mapowanie parametrów i zwracanie wartości do wymiany komunikatów
Operacje usługi są obsługiwane przez podstawową wymianę komunikatów PROTOKOŁU SOAP, które przesyłają dane aplikacji tam i z powrotem, oprócz danych wymaganych przez aplikację do obsługi niektórych standardowych funkcji zabezpieczeń, transakcji i sesji. Ponieważ tak jest, podpis operacji usługi nakazuje określony podstawowy wzorzec wymiany komunikatów (MEP), który może obsługiwać transfer danych i funkcje wymagane przez operację. W modelu programowania WCF można określić trzy wzorce: żądanie/odpowiedź, jednokierunkowe i dwukierunkowe wzorce komunikatów.
Żądanie/odpowiedź
Wzorzec żądania/odpowiedzi jest taki, w którym nadawca żądania (aplikacja kliencka) otrzymuje odpowiedź, z którą jest skorelowane żądanie. Jest to domyślny protokół MEP, ponieważ obsługuje operację, w której co najmniej jeden parametr jest przekazywany do operacji, a wartość zwracana jest przekazywana z powrotem do elementu wywołującego. Na przykład poniższy przykład kodu w języku C# przedstawia podstawową operację usługi, która przyjmuje jeden ciąg i zwraca ciąg.
[OperationContractAttribute]
string Hello(string greeting);
Poniżej znajduje się odpowiedni kod języka Visual Basic.
<OperationContractAttribute()>
Function Hello (ByVal greeting As String) As String
Ten podpis operacji określa formę podstawowej wymiany komunikatów. Jeśli żadna korelacja nie istniała, program WCF nie może określić, dla której operacji ma być przeznaczona wartość zwracana.
Należy pamiętać, że jeśli nie określisz innego podstawowego wzorca komunikatu, nawet operacje usługi, które zwracają void
wartość (Nothing
w Visual Basic), to wymiany komunikatów żądań/odpowiedzi. Wynikiem operacji jest to, że chyba że klient wywołuje operację asynchronicznie, klient przestaje przetwarzać do momentu odebrania komunikatu zwrotnego, mimo że ten komunikat jest pusty w normalnym przypadku. Poniższy przykład kodu w języku C# przedstawia operację, która nie zwraca się, dopóki klient nie otrzyma pustego komunikatu w odpowiedzi.
[OperationContractAttribute]
void Hello(string greeting);
Poniżej znajduje się odpowiedni kod języka Visual Basic.
<OperationContractAttribute()>
Sub Hello (ByVal greeting As String)
Powyższy przykład może spowolnić wydajność i czas odpowiedzi klienta, jeśli wykonanie operacji trwa długo, ale istnieją zalety operacji żądania/odpowiedzi, nawet gdy zwracają void
wartość . Najbardziej oczywistym jest to, że błędy protokołu SOAP mogą być zwracane w komunikacie odpowiedzi, co wskazuje, że wystąpił warunek błędu związany z usługą, niezależnie od tego, czy w komunikacji, czy w przetwarzaniu. Błędy protokołu SOAP określone w kontrakcie usługi są przekazywane do aplikacji klienckiej jako obiektu, gdzie parametr typu jest typem FaultException<TDetail> określonym w kontrakcie usługi. Dzięki temu klienci powiadamiania o warunkach błędów w usługach WCF są łatwe. Aby uzyskać więcej informacji na temat wyjątków, błędów protokołu SOAP i obsługi błędów, zobacz Określanie i obsługa błędów w kontraktach i usługach. Aby zapoznać się z przykładem usługi żądania/odpowiedzi i klienta, zobacz Instrukcje: tworzenie kontraktu żądania i odpowiedzi. Aby uzyskać więcej informacji na temat problemów ze wzorcem odpowiedzi na żądanie, zobacz Usługi żądań i odpowiedzi.
Jednokierunkowe
Jeśli klient aplikacji usługi WCF nie powinien czekać na ukończenie operacji i nie przetwarza błędów protokołu SOAP, operacja może określić wzorzec jednokierunkowego komunikatu. Jednokierunkowa operacja jest operacją, w której klient wywołuje operację i kontynuuje przetwarzanie po zapisaniu komunikatu w sieci przez program WCF. Zazwyczaj oznacza to, że jeśli dane wysyłane w komunikacie wychodzącym są bardzo duże, klient kontynuuje działanie niemal natychmiast (chyba że wystąpił błąd podczas wysyłania danych). Ten typ wzorca wymiany komunikatów obsługuje zachowanie podobne do zdarzeń od klienta do aplikacji usługi.
Wymiana komunikatów, w której jest wysyłany jeden komunikat i żadna nie jest odbierana, nie może obsługiwać operacji usługi, która określa wartość zwracaną inną niż void
; w tym przypadku InvalidOperationException zgłaszany jest wyjątek.
Żaden komunikat powrotny nie oznacza również, że nie może zostać zwrócony błąd PROTOKOŁU SOAP, aby wskazać błędy podczas przetwarzania lub komunikacji. (Komunikacja informacji o błędach, gdy operacje są operacjami jednokierunkowymi, wymagają wzorca dwukierunkowej wymiany komunikatów).
Aby określić jednokierunkową wymianę komunikatów dla operacji zwracającej void
wartość , ustaw IsOneWay właściwość na true
, jak w poniższym przykładzie kodu w języku C#.
[OperationContractAttribute(IsOneWay=true)]
void Hello(string greeting);
Poniżej znajduje się odpowiedni kod języka Visual Basic.
<OperationContractAttribute(IsOneWay := True)>
Sub Hello (ByVal greeting As String)
Ta metoda jest identyczna z powyższym przykładem żądania/odpowiedzi, ale ustawienie IsOneWay właściwości true
oznacza, że mimo że metoda jest identyczna, operacja usługi nie wysyła komunikatu zwrotnego, a klienci zwracają natychmiast po przekazaniu komunikatu wychodzącego do warstwy kanału. Przykład można znaleźć w temacie How to: Create a One-Way Contract (Instrukcje: tworzenie kontraktu jednokierunkowego). Aby uzyskać więcej informacji na temat wzorca jednokierunkowego, zobacz Usługi jednokierunkowe.
Dupleks
Wzorzec dupleksu charakteryzuje się możliwością zarówno usługi, jak i klienta do wysyłania komunikatów do siebie niezależnie, niezależnie od tego, czy używasz jednokierunkowej, czy komunikatów żądań/odpowiedzi. Ta forma dwukierunkowej komunikacji jest przydatna w przypadku usług, które muszą komunikować się bezpośrednio z klientem lub zapewnić środowisko asynchroniczne po obu stronach wymiany komunikatów, w tym zachowanie podobne do zdarzeń.
Wzorzec dwukierunkowy jest nieco bardziej złożony niż wzorce żądania/odpowiedzi lub jednokierunkowe ze względu na dodatkowy mechanizm komunikacji z klientem.
Aby zaprojektować kontrakt dwukierunkowy, należy również zaprojektować kontrakt wywołania zwrotnego i przypisać typ tego kontraktu wywołania zwrotnego do CallbackContract właściwości atrybutu ServiceContractAttribute , który oznacza kontrakt usługi.
Aby zaimplementować wzorzec dwukierunkowy, należy utworzyć drugi interfejs zawierający deklaracje metod wywoływane na kliencie.
Aby zapoznać się z przykładem tworzenia usługi i klienta, który uzyskuje dostęp do tej usługi, zobacz How to: Create a Duplex Contract (Jak utworzyć kontrakt dwukierunkowy) i How to: Usługi programu Access with a Duplex Contract (Instrukcje: Usługi programu Access z umową dwukierunkową). Aby zapoznać się z przykładem roboczym, zobacz Dupleks. Aby uzyskać więcej informacji na temat problemów z używaniem kontraktów dwukierunkowych, zobacz Usługi dwustronne.
Uwaga
Gdy usługa odbiera komunikat dwukierunkowy, analizuje ReplyTo
element w tej wiadomości przychodzącej, aby określić, gdzie wysłać odpowiedź. Jeśli kanał używany do odbierania komunikatu nie jest zabezpieczony, niezaufany klient może wysłać złośliwy komunikat z maszyną ReplyTo
docelową , co prowadzi do odmowy usługi (DOS) tej maszyny docelowej.
Parametry out i ref
W większości przypadków można użyć in
parametrów (ByVal
w Visual Basic) i ref
out
parametrów (ByRef
w Visual Basic). Ponieważ oba out
parametry i ref
wskazują, że dane są zwracane z operacji, podpis operacji, taki jak poniżej, określa, że operacja żądania/odpowiedzi jest wymagana, mimo że podpis operacji zwraca wartość void
.
[ServiceContractAttribute]
public interface IMyContract
{
[OperationContractAttribute]
public void PopulateData(ref CustomDataType data);
}
Poniżej znajduje się odpowiedni kod języka Visual Basic.
<ServiceContractAttribute()> _
Public Interface IMyContract
<OperationContractAttribute()> _
Public Sub PopulateData(ByRef data As CustomDataType)
End Interface
Jedynymi wyjątkami są przypadki, w których podpis ma określoną strukturę. Na przykład można użyć NetMsmqBinding powiązania do komunikowania się z klientami tylko wtedy, gdy metoda używana do deklarowania operacji zwraca void
wartość ; nie może istnieć wartość wyjściowa, niezależnie od tego, czy jest to wartość zwracana, ref
lub out
parametr.
Ponadto użycie parametrów out
lub ref
wymaga, aby operacja miała podstawowy komunikat odpowiedzi, aby przywrócić zmodyfikowany obiekt. Jeśli operacja jest operacją jednokierunkową, InvalidOperationException w czasie wykonywania jest zgłaszany wyjątek.
Określanie poziomu ochrony komunikatów w kontrakcie
Podczas projektowania kontraktu należy również zdecydować o poziomie ochrony komunikatów usług, które implementują kontrakt. Jest to konieczne tylko wtedy, gdy zabezpieczenia komunikatów są stosowane do powiązania w punkcie końcowym kontraktu. Jeśli powiązanie ma wyłączone zabezpieczenia (oznacza to, że jeśli powiązanie dostarczone przez system ustawia System.ServiceModel.SecurityMode wartość na wartość SecurityMode.None), nie trzeba decydować o poziomie ochrony komunikatów dla kontraktu. W większości przypadków powiązania dostarczone przez system z zastosowanymi zabezpieczeniami na poziomie komunikatu zapewniają wystarczający poziom ochrony i nie trzeba uwzględniać poziomu ochrony dla każdej operacji lub dla każdego komunikatu.
Poziom ochrony to wartość określająca, czy komunikaty (lub części komunikatów), które obsługują usługę, są podpisane, podpisane i szyfrowane, czy wysyłane bez podpisów lub szyfrowania. Poziom ochrony można ustawić w różnych zakresach: na poziomie usługi dla określonej operacji dla komunikatu w ramach tej operacji lub części komunikatu. Wartości ustawione w jednym zakresie stają się wartością domyślną dla mniejszych zakresów, chyba że jawnie przesłonięć. Jeśli konfiguracja powiązania nie może zapewnić wymaganego minimalnego poziomu ochrony dla kontraktu, zgłaszany jest wyjątek. A jeśli nie ustawiono jawnie wartości na poziomie ochrony w umowie, konfiguracja powiązania kontroluje poziom ochrony dla wszystkich komunikatów, jeśli powiązanie ma zabezpieczenia komunikatów. To jest zachowanie domyślne.
Ważne
Podjęcie decyzji, czy jawnie ustawić różne zakresy umowy na mniej niż pełny poziom ochrony, ProtectionLevel.EncryptAndSign jest zazwyczaj decyzją, która wymienia pewien stopień bezpieczeństwa w celu zwiększenia wydajności. W takich przypadkach decyzje muszą się obracać wokół operacji i wartości wymienianych danych. Aby uzyskać więcej informacji, zobacz Zabezpieczanie usług.
Na przykład poniższy przykład kodu nie ustawia ProtectionLevel właściwości lub ProtectionLevel w kontrakcie.
[ServiceContract]
public interface ISampleService
{
[OperationContractAttribute]
public string GetString();
[OperationContractAttribute]
public int GetInt();
}
Poniżej znajduje się odpowiedni kod języka Visual Basic.
<ServiceContractAttribute()> _
Public Interface ISampleService
<OperationContractAttribute()> _
Public Function GetString()As String
<OperationContractAttribute()> _
Public Function GetData() As Integer
End Interface
Podczas interakcji z implementacją ISampleService
w punkcie końcowym z wartością domyślną (domyślną WSHttpBinding , czyli Message), System.ServiceModel.SecurityModewszystkie komunikaty są szyfrowane i podpisane, ponieważ jest to domyślny poziom ochrony. Jednak gdy ISampleService
usługa jest używana z wartością domyślną BasicHttpBinding (domyślną SecurityMode, czyli None), wszystkie komunikaty są wysyłane jako tekst, ponieważ nie ma żadnych zabezpieczeń dla tego powiązania i dlatego poziom ochrony jest ignorowany (oznacza to, że komunikaty nie są ani szyfrowane, ani podpisane). Jeśli element SecurityMode został zmieniony na Message, te komunikaty zostaną zaszyfrowane i podpisane (ponieważ będzie to teraz domyślny poziom ochrony powiązania).
Jeśli chcesz jawnie określić lub dostosować wymagania dotyczące ochrony dla kontraktu, ustaw ProtectionLevel właściwość (lub dowolną ProtectionLevel
z właściwości w mniejszym zakresie) na poziom wymagany przez umowę serwisową. W takim przypadku użycie jawnego ustawienia wymaga powiązania, aby obsługiwać to ustawienie co najmniej dla używanego zakresu. Na przykład poniższy przykład kodu określa jedną ProtectionLevel wartość jawnie dla GetGuid
operacji.
[ServiceContract]
public interface IExplicitProtectionLevelSampleService
{
[OperationContractAttribute]
public string GetString();
[OperationContractAttribute(ProtectionLevel=ProtectionLevel.None)]
public int GetInt();
[OperationContractAttribute(ProtectionLevel=ProtectionLevel.EncryptAndSign)]
public int GetGuid();
}
Poniżej znajduje się odpowiedni kod języka Visual Basic.
<ServiceContract()> _
Public Interface IExplicitProtectionLevelSampleService
<OperationContract()> _
Public Function GetString() As String
End Function
<OperationContract(ProtectionLevel := ProtectionLevel.None)> _
Public Function GetInt() As Integer
End Function
<OperationContractAttribute(ProtectionLevel := ProtectionLevel.EncryptAndSign)> _
Public Function GetGuid() As Integer
End Function
End Interface
Usługa, która implementuje ten IExplicitProtectionLevelSampleService
kontrakt i ma punkt końcowy, który używa domyślnego WSHttpBinding (domyślnego System.ServiceModel.SecurityMode, czyli Message) ma następujące zachowanie:
Komunikaty
GetString
operacji są szyfrowane i podpisane.Komunikaty
GetInt
operacji są wysyłane jako niezaszyfrowane i niepodpisane (czyli zwykły) tekst.Operacja
GetGuid
System.Guid jest zwracana w komunikacie zaszyfrowanym i podpisanym.
Aby uzyskać więcej informacji na temat poziomów ochrony i sposobu ich używania, zobacz Opis poziomu ochrony. Aby uzyskać więcej informacji na temat zabezpieczeń, zobacz Zabezpieczanie usług.
Inne wymagania dotyczące podpisu operacji
Niektóre funkcje aplikacji wymagają określonego rodzaju podpisu operacji. Na przykład NetMsmqBinding powiązanie obsługuje trwałe usługi i klientów, w których aplikacja może ponownie uruchomić aplikację w trakcie komunikacji i odebrać miejsce, w którym została przerwana bez braku komunikatów. (Aby uzyskać więcej informacji, zobacz Kolejki w programie WCF). Jednak operacje trwałe muszą przyjmować tylko jeden in
parametr i nie mają wartości zwracanej.
Innym przykładem jest użycie Stream typów w operacjach. Stream Ponieważ parametr zawiera całą treść komunikatu, jeśli dane wejściowe lub wyjściowe (czyli parametr, ref
out
parametr lub wartość zwracana) mają typ Stream, musi to być jedyne dane wejściowe lub wyjściowe określone w operacji. Ponadto parametr lub zwracany typ musi mieć Streamwartość , System.ServiceModel.Channels.Messagelub System.Xml.Serialization.IXmlSerializable. Aby uzyskać więcej informacji na temat strumieni, zobacz Duże dane i przesyłanie strumieniowe.
Nazwy, przestrzenie nazw i zaciemnianie
Nazwy i przestrzenie nazw typów platformy .NET w definicji kontraktów i operacji są istotne, gdy kontrakty są konwertowane na WSDL i kiedy komunikaty kontraktów są tworzone i wysyłane. Dlatego zdecydowanie zaleca się, aby nazwy kontraktów usług i przestrzenie nazw zostały jawnie ustawione przy użyciu Name
właściwości i Namespace
wszystkich atrybutów kontraktu pomocniczego, takich jak ServiceContractAttribute, OperationContractAttribute, DataContractAttribute, DataMemberAttributei inne atrybuty kontraktu.
Jednym z tych wyników jest to, że jeśli nazwy i przestrzenie nazw nie są jawnie ustawione, użycie zaciemniania IL w zestawie zmienia nazwy typów kontraktów i przestrzeni nazw i powoduje modyfikację WSDL i wymiany przewodów, które zwykle kończą się niepowodzeniem. Jeśli nie ustawisz jawnie nazw kontraktów i przestrzeni nazw, ale zamierzasz używać zaciemniania, użyj ObfuscationAttribute atrybutów i ObfuscateAssemblyAttribute , aby zapobiec modyfikacji nazw typów kontraktów i przestrzeni nazw.
Zobacz też
- Instrukcje: tworzenie kontraktu „żądanie-odpowiedź”
- Instrukcje: tworzenie kontraktu jednokierunkowego
- Instrukcje: tworzenie kontraktu dwukierunkowego
- Określanie transferu danych w kontraktach usług
- Określanie i obsługa błędów w kontraktach i usługach
- Korzystanie z sesji
- Operacje synchroniczne i asynchroniczne
- Usługi Reliable Services
- Usługi i transakcje