Navrhování kontraktů služby
Toto téma popisuje, co jsou kontrakty služeb, jak jsou definované, jaké operace jsou k dispozici (a jaké jsou důsledky pro podkladové výměny zpráv), jaké datové typy se používají, a další problémy, které vám pomůžou navrhovat operace, které splňují požadavky vašeho scénáře.
Vytvoření kontraktu služby
Služby zpřístupňují řadu operací. V aplikacích WCF (Windows Communication Foundation) definujte operace vytvořením metody a jeho označení atributem OperationContractAttribute . Potom vytvořte kontrakt služby, seskupte své operace buď deklarováním v rámci rozhraní označeného ServiceContractAttribute atributem, nebo jejich definováním ve třídě označené stejným atributem. (Základní příklad najdete v tématu Postupy: Definování kontraktu služby.)
Žádné metody, které nemají OperationContractAttribute atribut, nejsou operace služby a nejsou vystaveny službami WCF.
Toto téma popisuje následující rozhodovací body při návrhu kontraktu služby:
Bez ohledu na to, jestli se mají používat třídy nebo rozhraní.
Jak zadat datové typy, které chcete vyměnit.
Typy vzorů výměny, které můžete použít.
Určuje, jestli je součástí smlouvy explicitní požadavky na zabezpečení.
Omezení pro vstupy a výstupy operací.
Třídy nebo rozhraní
Třídy i rozhraní představují seskupení funkcí, a proto lze obojí použít k definování kontraktu služby WCF. Doporučujeme ale používat rozhraní, protože přímo modelují kontrakty služeb. Bez implementace rozhraní nedefinují více než definování seskupení metod s určitými podpisy. Implementujte rozhraní kontraktu služby a implementovali jste službu WCF.
Všechny výhody spravovaných rozhraní platí pro rozhraní kontraktů služeb:
Rozhraní kontraktů služeb můžou rozšířit libovolný počet dalších rozhraní kontraktů služeb.
Jedna třída může implementovat libovolný počet kontraktů služeb implementací těchto rozhraní kontraktů služeb.
Implementaci kontraktu služby můžete upravit změnou implementace rozhraní, zatímco kontrakt služby zůstane stejný.
Službu můžete vytvořit verzí implementací starého rozhraní a nového rozhraní. Starší klienti se připojují k původní verzi, zatímco novější klienti se můžou připojit k novější verzi.
Poznámka:
Při dědění z jiných rozhraní kontraktů služeb nelze přepsat vlastnosti operace, jako je název nebo obor názvů. Pokud se to pokusíte provést, vytvoříte novou operaci v aktuálním kontraktu služby.
Příklad použití rozhraní k vytvoření kontraktu služby naleznete v tématu Postupy: Vytvoření služby s rozhraním kontraktu.
Můžete však použít třídu k definování kontraktu služby a implementaci této smlouvy ve stejnou dobu. Výhodou vytváření služeb pomocí použití ServiceContractAttribute a OperationContractAttribute přímo u třídy a metod ve třídě je rychlost a jednoduchost. Nevýhody jsou, že spravované třídy nepodporují více dědičnosti a v důsledku toho mohou implementovat pouze jeden kontrakt služby najednou. Kromě toho všechny úpravy podpisů třídy nebo metody mění veřejnou smlouvu pro tuto službu, což může zabránit, aby nemodifikovaní klienti používali vaši službu. Další informace naleznete v tématu Implementace kontraktů služeb.
Příklad, který používá třídu k vytvoření kontraktu služby a implementuje ji ve stejnou dobu, viz Postupy: Vytvoření služby s třídou kontraktu.
V tomto okamžiku byste měli porozumět rozdílu mezi definováním kontraktu služby pomocí rozhraní a pomocí třídy. Dalším krokem je rozhodnutí o tom, jaká data se dají předávat mezi službou a jejími klienty.
Parametry a návratové hodnoty
Každá operace má návratovou hodnotu a parametr, i když jsou void
. Na rozdíl od místní metody, ve které můžete předávat odkazy na objekty z jednoho objektu do druhého, operace služby nepředají odkazy na objekty. Místo toho předávají kopie objektů.
To je důležité, protože každý typ použitý v parametru nebo návratové hodnotě musí být serializovatelný; to znamená, že musí být možné převést objekt tohoto typu na datový proud bajtů a z datového proudu bajtů na objekt.
Primitivní typy jsou ve výchozím nastavení serializovatelné, stejně jako mnoho typů v rozhraní .NET Framework.
Poznámka:
Hodnota názvů parametrů v podpisu operace je součástí kontraktu a rozlišují se malá a velká písmena. Pokud chcete použít stejný název parametru místně, ale změnit název v publikovaných metadatech, přečtěte si téma System.ServiceModel.MessageParameterAttribute.
Kontrakty dat
Aplikace orientované na služby, jako jsou aplikace WCF (Windows Communication Foundation), jsou navržené tak, aby interoperačně s co nejširším počtem klientských aplikací na platformách Microsoftu i jiných společností než Microsoft. Pro co nejširší možnou interoperabilitu doporučujeme označit typy pomocí DataContractAttribute atributů a DataMemberAttribute vytvořit kontrakt dat, což je část kontraktu služby, která popisuje data, která vaše operace služby vyměňují.
Kontrakty dat jsou kontrakty ve stylu výslovného souhlasu: Není serializován žádný typ nebo datový člen, pokud explicitně nepoužijete atribut datového kontraktu. Kontrakty dat nesouvisejí s oborem přístupu spravovaného kódu: Soukromé datové členy je možné serializovat a posílat na jiné místo, kde budou veřejně přístupné. (Základní příklad kontraktu dat najdete v tématu Postupy: Vytvoření základního kontraktu dat pro třídu nebo strukturu.) WCF zpracovává definici podkladových zpráv SOAP, které umožňují fungování operace a také serializaci datových typů do textu zpráv a z textu zpráv. Pokud jsou datové typy serializovatelné, nemusíte při navrhování operací přemýšlet o základní infrastruktuře výměny zpráv.
I když typická aplikace WCF používá DataContractAttribute a DataMemberAttribute atributy k vytváření datových kontraktů pro operace, můžete použít jiné mechanismy serializace. Standardní ISerializable, SerializableAttributea IXmlSerializable mechanismy všechny pracují na zpracování serializace datových typů do podkladových zpráv SOAP, které je přenášejí z jedné aplikace do druhé. Pokud datové typy vyžadují zvláštní podporu, můžete použít více strategií serializace. Další informace o možnostech serializace datových typů v aplikacích WCF naleznete v tématu Určení přenosu dat v kontraktech služeb.
Mapování parametrů a návratových hodnot do výměn zpráv
Operace služby jsou podporovány základní výměnou zpráv SOAP, které přenášejí data aplikací zpět a zpět, a navíc k datům vyžadovaným aplikací pro podporu určitých standardních funkcí zabezpečení, transakcí a relací. Vzhledem k tomu, že se jedná o tento případ, podpis operace služby určuje určitý základní vzor výměny zpráv (MEP), který může podporovat přenos dat a funkce, které operace vyžaduje. V programovacím modelu WCF můžete zadat tři vzory: požadavky a odpovědi, jednosměrné a duplexní vzory zpráv.
Žádost/odpověď
Vzor požadavku nebo odpovědi je ten, ve kterém odesílatel požadavku (klientská aplikace) obdrží odpověď, se kterou požadavek koreluje. Toto je výchozí mep, protože podporuje operaci, ve které jsou předány jeden nebo více parametrů operaci a návratová hodnota je předána zpět volajícímu. Například následující příklad kódu jazyka C# ukazuje základní operaci služby, která přijímá jeden řetězec a vrací řetězec.
[OperationContractAttribute]
string Hello(string greeting);
Následuje ekvivalentní kód jazyka Visual Basic.
<OperationContractAttribute()>
Function Hello (ByVal greeting As String) As String
Tento podpis operace určuje formu podkladové výměny zpráv. Pokud neexistuje žádná korelace, WCF nemůže určit, pro kterou operaci je vrácená hodnota určena.
Mějte na paměti, že pokud nezadáte jiný základní vzor zpráv, ani operace služby, které se vrátí void
(Nothing
v jazyce Visual Basic), budou výměny zpráv žádostí a odpovědí. Výsledkem operace je, že pokud klient operaci nevolá asynchronně, klient přestane zpracovávat, dokud se neobdrží vrácená zpráva, i když je tato zpráva v normálním případě prázdná. Následující příklad kódu jazyka C# ukazuje operaci, která se nevrací, dokud klient neobdrží prázdnou zprávu v odpovědi.
[OperationContractAttribute]
void Hello(string greeting);
Následuje ekvivalentní kód jazyka Visual Basic.
<OperationContractAttribute()>
Sub Hello (ByVal greeting As String)
Předchozí příklad může zpomalit výkon klienta a rychlost odezvy, pokud operace trvá dlouhou dobu, ale existují výhody pro operace žádosti a odpovědi, i když se vrátí void
. Nejobjasnější je, že chyby PROTOKOLU SOAP je možné vrátit ve zprávě odpovědi, která indikuje, že došlo k nějakému chybovému stavu souvisejícímu se službou, ať už při komunikaci nebo zpracování. Chyby protokolu SOAP zadané ve smlouvě služby se předávají klientské aplikaci jako FaultException<TDetail> objekt, kde parametr typu je typ zadaný v kontraktu služby. To usnadňuje oznamování klientům o chybových podmínkách ve službách WCF. Další informace o výjimkách, chybách SOAP a zpracování chyb naleznete v tématu Určení a zpracování chyb v kontraktech a službách. Příklad služby žádosti/odpovědi a klienta najdete v tématu Postupy: Vytvoření smlouvy žádosti a odpovědi. Další informace o problémech se vzorem žádosti a odpovědi najdete v tématu Služby pro odpovědi na žádosti.
Jednosměrné
Pokud klient aplikace služby WCF by neměl čekat na dokončení operace a nezpracovává chyby PROTOKOLU SOAP, může operace zadat jednosměrný vzor zpráv. Jednosměrná operace je operace, ve které klient vyvolá operaci a pokračuje ve zpracování poté, co WCF zapíše zprávu do sítě. Obvykle to znamená, že pokud nejsou data odesílaná ve odchozí zprávě extrémně velká, klient pokračuje téměř okamžitě (pokud nedojde k chybě při odesílání dat). Tento typ vzoru výměny zpráv podporuje chování podobné událostem z klienta do aplikace služby.
Výměna zpráv, ve které je odeslána jedna zpráva a žádné nejsou přijaty, nemůže podporovat operaci služby, která určuje jinou návratovou hodnotu než void
; v tomto případě InvalidOperationException je vyvolána výjimka.
Žádná návratová zpráva také znamená, že se nemůže vrátit žádná chyba PROTOKOLU SOAP, která značí případné chyby při zpracování nebo komunikaci. (Komunikace informací o chybách v případě, že operace jsou jednosměrné operace, vyžadují oboustranný vzor výměny zpráv.)
Chcete-li zadat jednosměrnou výměnu zpráv pro operaci, která vrací void
, nastavte IsOneWay vlastnost na true
, jako v následujícím příkladu kódu jazyka C#.
[OperationContractAttribute(IsOneWay=true)]
void Hello(string greeting);
Následuje ekvivalentní kód jazyka Visual Basic.
<OperationContractAttribute(IsOneWay := True)>
Sub Hello (ByVal greeting As String)
Tato metoda je shodná s předchozím příkladem požadavku/odpovědi, ale nastavení IsOneWay vlastnosti na true
hodnotu znamená, že i když je metoda identická, operace služby neodešle návratovou zprávu a klienti se okamžitě vrátí, jakmile je odchozí zpráva předána vrstvě kanálu. Příklad najdete v tématu Postupy: Vytvoření jednosměrného kontraktu. Další informace o jednosměrné cestě naleznete v tématu Jednosměrné služby.
Duplex
Duplexní vzor je charakterizován schopností služby i klienta posílat zprávy mezi sebou nezávisle na tom, zda pomocí jednosměrného zasílání zpráv nebo zasílání žádostí nebo odpovědí. Tato forma obousměrné komunikace je užitečná pro služby, které musí komunikovat přímo s klientem nebo pro poskytování asynchronního prostředí na obou stranách výměny zpráv, včetně chování podobné události.
Duplexní vzor je o něco složitější než vzory žádosti/odpovědi nebo jednosměrné vzory kvůli dalšímu mechanismu pro komunikaci s klientem.
Chcete-li navrhnout duplexní kontrakt, musíte také navrhnout kontrakt zpětného volání a přiřadit typ této smlouvy zpětného volání k CallbackContract vlastnosti atributu ServiceContractAttribute , který označuje vaši smlouvu služby.
Chcete-li implementovat duplexní vzor, je nutné vytvořit druhé rozhraní, které obsahuje deklarace metody, které jsou volány v klientovi.
Příklad vytvoření služby a klienta, který přistupuje k této službě, najdete v tématu Postupy: Vytvoření duplexního kontraktu a postupy: Přístup ke službám pomocí duplexního kontraktu. Pracovní ukázku najdete v tématu Duplex. Další informace o problémech s používáním duplexního kontraktu naleznete v tématu Duplex Services.
Upozornění
Když služba obdrží duplexní zprávu, podívá se na ReplyTo
prvek v této příchozí zprávě a určí, kam se má odpověď odeslat. Pokud kanál, který se používá k přijetí zprávy, není zabezpečený, může nedůvěryhodný klient odeslat škodlivou zprávu s cílovým počítačem ReplyTo
, což vede k odepření služby (DOS) tohoto cílového počítače.
Parametry Out a Ref
Ve většině případů můžete použít in
parametry (ByVal
v jazyce Visual Basic) a ref
out
parametry (ByRef
v jazyce Visual Basic). Vzhledem k tomu, že oba out
parametry ref
označují, že data jsou vrácena z operace, podpis operace, například následující, určuje, že operace požadavku nebo odpovědi je nutná, i když podpis operace vrátí void
.
[ServiceContractAttribute]
public interface IMyContract
{
[OperationContractAttribute]
public void PopulateData(ref CustomDataType data);
}
Následuje ekvivalentní kód jazyka Visual Basic.
<ServiceContractAttribute()> _
Public Interface IMyContract
<OperationContractAttribute()> _
Public Sub PopulateData(ByRef data As CustomDataType)
End Interface
Jedinou výjimkou jsou případy, ve kterých má váš podpis konkrétní strukturu. Můžete například použít NetMsmqBinding vazbu ke komunikaci s klienty pouze v případě, že metoda použitá k deklaraci operace vrátí ; void
nemůže existovat žádná výstupní hodnota, bez ohledu na to, zda se jedná o návratovou hodnotu, ref
nebo out
parametr.
Kromě toho použití out
nebo ref
parametry vyžaduje, aby operace měla podkladovou zprávu odpovědi k přenosu upraveného objektu. Pokud je vaše operace jednosměrná, vyvolá InvalidOperationException se výjimka za běhu.
Zadání úrovně ochrany zpráv pro kontrakt
Při návrhu smlouvy musíte také rozhodnout o úrovni ochrany zpráv služeb, které vaši smlouvu implementují. To je nezbytné pouze v případě, že se na vazbu v koncovém bodu kontraktu použije zabezpečení zpráv. Pokud je u vazby vypnuté zabezpečení (to znamená, že pokud systémová vazba nastaví System.ServiceModel.SecurityMode hodnotu SecurityMode.None), nemusíte se rozhodnout o úrovni ochrany zpráv pro kontrakt. Ve většině případů systémové vazby s použitým zabezpečením na úrovni zpráv poskytují dostatečnou úroveň ochrany a nemusíte brát v úvahu úroveň ochrany pro každou operaci nebo pro každou zprávu.
Úroveň ochrany je hodnota, která určuje, jestli jsou zprávy (nebo části zpráv) podporující službu podepsané, podepsané a šifrované nebo odeslané bez podpisů nebo šifrování. Úroveň ochrany lze nastavit v různých oborech: Na úrovni služby, pro konkrétní operaci, pro zprávu v rámci této operace nebo část zprávy. Hodnoty nastavené v jednom oboru se stanou výchozí hodnotou pro menší obory, pokud explicitně nepřepíšete. Pokud konfigurace vazby nemůže poskytnout požadovanou minimální úroveň ochrany kontraktu, vyvolá se výjimka. A pokud ve smlouvě nejsou explicitně nastaveny žádné hodnoty úrovně ochrany, konfigurace vazby řídí úroveň ochrany pro všechny zprávy, pokud má vazba zabezpečení zpráv. Toto je výchozí chování.
Důležité
Rozhodnutí, zda explicitně nastavit různé rozsahy smlouvy na nižší, než je úplná úroveň ProtectionLevel.EncryptAndSign ochrany, je obecně rozhodnutí, které obchoduje s určitou mírou zabezpečení za účelem zvýšení výkonu. V těchto případech se vaše rozhodnutí musí týkat vašich operací a hodnoty dat, která si vyměňují. Další informace naleznete v tématu Zabezpečení služeb.
Například následující příklad kódu nenastaví ProtectionLevelProtectionLevel ani vlastnost kontraktu.
[ServiceContract]
public interface ISampleService
{
[OperationContractAttribute]
public string GetString();
[OperationContractAttribute]
public int GetInt();
}
Následuje ekvivalentní kód jazyka Visual Basic.
<ServiceContractAttribute()> _
Public Interface ISampleService
<OperationContractAttribute()> _
Public Function GetString()As String
<OperationContractAttribute()> _
Public Function GetData() As Integer
End Interface
Při interakci s ISampleService
implementací v koncovém bodu s výchozí WSHttpBinding (výchozí System.ServiceModel.SecurityMode, což znamená Message), jsou všechny zprávy šifrované a podepsané, protože se jedná o výchozí úroveň ochrany. Pokud ISampleService
se však služba používá s výchozím nastavením BasicHttpBinding (výchozí SecurityMode, což znamená None), všechny zprávy se posílají jako text, protože pro tuto vazbu není žádné zabezpečení, a proto je úroveň ochrany ignorována (to znamená, že zprávy nejsou šifrované ani podepsané). Pokud byl změněn na SecurityModeMessage, tyto zprávy by se zašifrovaly a podepsaly (protože by to teď byla výchozí úroveň ochrany vazby).
Pokud chcete explicitně zadat nebo upravit požadavky na ochranu pro vaši smlouvu, nastavte ProtectionLevel vlastnost (nebo některou z ProtectionLevel
vlastností v menším rozsahu) na úroveň, kterou vyžaduje smlouva o poskytování služeb. V tomto případě použití explicitního nastavení vyžaduje, aby vazba podporovala toto nastavení minimálně pro použitý obor. Například následující příklad kódu určuje jednu ProtectionLevel hodnotu explicitně pro GetGuid
operaci.
[ServiceContract]
public interface IExplicitProtectionLevelSampleService
{
[OperationContractAttribute]
public string GetString();
[OperationContractAttribute(ProtectionLevel=ProtectionLevel.None)]
public int GetInt();
[OperationContractAttribute(ProtectionLevel=ProtectionLevel.EncryptAndSign)]
public int GetGuid();
}
Následuje ekvivalentní kód jazyka 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
Služba, která implementuje tento IExplicitProtectionLevelSampleService
kontrakt a má koncový bod, který používá výchozí WSHttpBinding (výchozí System.ServiceModel.SecurityMode, což je Message) má následující chování:
Zprávy
GetString
operace jsou šifrované a podepsané.Zprávy
GetInt
operací se odesílají jako nešifrovaný a nepodepsaný (tj. prostý text).Operace
GetGuid
System.Guid se vrátí ve zprávě, která je zašifrovaná a podepsaná.
Další informace o úrovních ochrany a jejich použití najdete v tématu Principy úrovně ochrany. Další informace o zabezpečení naleznete v tématu Zabezpečení služeb.
Další požadavky na podpis operace
Některé funkce aplikace vyžadují určitý druh podpisu operace. Vazba například NetMsmqBinding podporuje odolné služby a klienty, ve kterých se aplikace může restartovat uprostřed komunikace a vyzvednout tam, kde skončila, aniž by chyběly žádné zprávy. (Další informace najdete v tématu Fronty ve WCF.) Trvalé operace však musí mít pouze jeden in
parametr a nemají žádnou návratnou hodnotu.
Dalším příkladem je použití typů v operacích Stream . Protože parametr Stream obsahuje celý text zprávy, je-li vstup nebo výstup (tj ref
. parametr, out
parametr nebo návratová hodnota) typu Stream, pak musí být jediným vstupem nebo výstupem zadaným ve vaší operaci. Kromě toho musí být parametr nebo návratový typ buď Stream, System.ServiceModel.Channels.Messagenebo System.Xml.Serialization.IXmlSerializable. Další informace o datových proudech najdete v tématu Velké objemy dat a streamování.
Názvy, obory názvů a obfuskace
Názvy a obory názvů typů .NET v definici kontraktů a operací jsou významné při převodu kontraktů na WSDL a při vytváření a odesílání zpráv kontraktů. Proto důrazně doporučujeme, aby názvy a obory názvů služeb byly explicitně nastaveny pomocí Name
a Namespace
vlastnosti všech podpůrných atributů kontraktů, jako ServiceContractAttributejsou například , , DataContractAttributeOperationContractAttribute, DataMemberAttributea další atributy kontraktu.
Jedním z těchto výsledků je, že pokud názvy a obory názvů nejsou explicitně nastaveny, použití obfuskace IL v sestavení změní názvy typů kontraktů a obory názvů a vede k změně WSDL a výměny drátů, které obvykle selžou. Pokud názvy kontraktů a obory názvů nenastavíte explicitně, ale hodláte použít obfuskaci, použijte ObfuscationAttribute a ObfuscateAssemblyAttribute atributy, abyste zabránili úpravám názvů a oborů názvů kontraktů.
Viz také
- Postupy: Vytvoření kontraktu žádosti a odpovědi
- Postupy: Vytvoření jednosměrného kontraktu
- Postupy: Vytvoření duplexního kontraktu
- Určování přenosu dat v kontraktech služby
- Určování a zpracování chyb v kontraktech a službách
- Použití relací
- Synchronní a asynchronní operace
- Reliable Services
- Služby a transakce