Používání třídy Message
Třída Message je zásadní pro Windows Communication Foundation (WCF). Veškerá komunikace mezi klienty a službami nakonec vede k Message odesílání a přijetí instancí.
Obvykle byste s třídou nepracují Message přímo. Místo toho se k popisu příchozích a odchozích zpráv používají konstrukty modelu služby WCF, jako jsou kontrakty dat, kontrakty zpráv a kontrakty operací. V některých pokročilých scénářích ale můžete programovat přímo pomocí Message třídy. Můžete například chtít použít Message třídu:
Pokud potřebujete alternativní způsob vytváření obsahu odchozích zpráv (například vytvoření zprávy přímo ze souboru na disku) místo serializace objektů rozhraní .NET Framework.
Pokud potřebujete alternativní způsob použití obsahu příchozích zpráv (například pokud chcete použít transformaci XSLT na nezpracovaný obsah XML) místo deserializace do objektů rozhraní .NET Framework.
Pokud potřebujete zpracovávat zprávy obecným způsobem bez ohledu na obsah zpráv (například při směrování nebo přeposílání zpráv při vytváření směrovače, nástroje pro vyrovnávání zatížení nebo systému publikování a odběru).
Před použitím Message třídy se seznamte s architekturou přenosu dat WCF v přehledu architektury přenosu dat.
A Message je kontejner pro obecné účely pro data, ale jeho návrh úzce sleduje návrh zprávy v protokolu SOAP. Stejně jako v protokolu SOAP má zpráva jak text zprávy, tak záhlaví. Text zprávy obsahuje skutečná data datové části, zatímco záhlaví obsahují další pojmenované datové kontejnery. Pravidla pro čtení a zápis textu a záhlaví se liší, například záhlaví se vždy ukládají do vyrovnávací paměti a můžou být přístupná v libovolném pořadí, zatímco tělo může být přečteno pouze jednou a může být streamováno. Při použití protokolu SOAP se text zprávy mapuje na tělo protokolu SOAP a záhlaví zprávy se mapují na hlavičky SOAP.
Použití třídy zpráv v operacích
Třídu můžete použít Message jako vstupní parametr operace, návratovou hodnotu operace nebo obojí. Pokud Message se používá kdekoli v operaci, platí následující omezení:
Operace nemůže mít žádné
out
parametry aniref
parametry.Nemůže existovat více než jeden
input
parametr. Pokud je parametr k dispozici, musí to být zpráva nebo typ kontraktu zprávy.Návratový typ musí být buď
void
,Message
nebo typ kontraktu zprávy.
Následující příklad kódu obsahuje platný kontrakt operace.
[ServiceContract]
public interface IMyService
{
[OperationContract]
Message GetData();
[OperationContract]
void PutData(Message m);
}
<ServiceContract()> _
Public Interface IMyService
<OperationContract()> _
Function GetData() As Message
<OperationContract()> _
Sub PutData(ByVal m As Message)
End Interface
Vytváření základních zpráv
Třída Message poskytuje statické CreateMessage
metody továrny, které můžete použít k vytváření základních zpráv.
Všechna CreateMessage
přetížení přebírají parametr verze typu MessageVersion , který označuje verze SOAP a WS-Addressing verze, které se mají použít pro zprávu. Pokud chcete použít stejné verze protokolu jako příchozí zpráva, můžete použít IncomingMessageVersion vlastnost u OperationContext instance získané z Current vlastnosti. Většina CreateMessage
přetížení má také řetězcový parametr, který označuje akci SOAP, která se má použít pro zprávu. Verzi je možné nastavit tak, aby None
se zakázalo generování obálky SOAP. Zpráva se skládá pouze z textu.
Vytváření zpráv z objektů
Nejzásadnější CreateMessage
přetížení, které přijímá pouze verzi a akce vytvoří zprávu s prázdným tělem. Další přetížení přebírá další Object parametr; tím se vytvoří zpráva, jejíž tělo je serializovaná reprezentace daného objektu. DataContractSerializer Použijte výchozí nastavení pro serializaci. Pokud chcete použít jiný serializátor nebo chcete DataContractSerializer
nakonfigurovat jinak, použijte CreateMessage
přetížení, které také přebírá XmlObjectSerializer
parametr.
Pokud chcete například vrátit objekt ve zprávě, můžete použít následující kód.
public class MyService1 : IMyService
{
public Message GetData()
{
Person p = new Person();
p.name = "John Doe";
p.age = 42;
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
return Message.CreateMessage(ver, "GetDataResponse", p);
}
public void PutData(Message m)
{
// Not implemented.
}
}
[DataContract]
public class Person
{
[DataMember] public string name;
[DataMember] public int age;
}
Public Class MyService1
Implements IMyService
Public Function GetData() As Message _
Implements IMyService.GetData
Dim p As New Person()
p.name = "John Doe"
p.age = 42
Dim ver As MessageVersion = _
OperationContext.Current.IncomingMessageVersion
Return Message.CreateMessage(ver, "GetDataResponse", p)
End Function
Public Sub PutData(ByVal m As Message) _
Implements IMyService.PutData
' Not implemented.
End Sub
End Class
<DataContract()> _
Public Class Person
<DataMember()> _
Public name As String
<DataMember()> _
Public age As Integer
End Class
Vytváření zpráv ze čteček XML
CreateMessage
Existují přetížení, která přebírají tělo XmlReader nebo XmlDictionaryReader pro tělo místo objektu. V tomto případě obsahuje text zprávy XML, který je výsledkem čtení z předané čtečky XML. Například následující kód vrátí zprávu s obsahem textu načteným ze souboru XML.
public class MyService2 : IMyService
{
public Message GetData()
{
FileStream stream = new FileStream("myfile.xml",FileMode.Open);
XmlDictionaryReader xdr =
XmlDictionaryReader.CreateTextReader(stream,
new XmlDictionaryReaderQuotas());
MessageVersion ver =
OperationContext.Current.IncomingMessageVersion;
return Message.CreateMessage(ver,"GetDataResponse",xdr);
}
public void PutData(Message m)
{
// Not implemented.
}
}
Public Class MyService2
Implements IMyService
Public Function GetData() As Message Implements IMyService.GetData
Dim stream As New FileStream("myfile.xml", FileMode.Open)
Dim xdr As XmlDictionaryReader = _
XmlDictionaryReader.CreateTextReader(stream, New XmlDictionaryReaderQuotas())
Dim ver As MessageVersion = OperationContext.Current.IncomingMessageVersion
Return Message.CreateMessage(ver, "GetDataResponse", xdr)
End Function
Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
End Sub
End Class
Kromě toho existují CreateMessage
přetížení, které přebírají XmlReader nebo XmlDictionaryReader představují celou zprávu, a ne jen tělo. Tato přetížení také přebírají celočíselnou maxSizeOfHeaders
hodnotu parametru. Hlavičky se vždy ukládají do paměti, jakmile se zpráva vytvoří, a tento parametr omezuje množství ukládání do vyrovnávací paměti, které probíhá. Tento parametr je důležité nastavit na bezpečnou hodnotu, pokud XML pochází z nedůvěryhodného zdroje, aby se zmírnit možnost útoku dos. Verze SOAP a WS-Adresování zprávy, kterou čtečka XML představuje, musí odpovídat verzím uvedeným pomocí parametru verze.
Vytváření zpráv pomocí bodyWriter
Jedno CreateMessage
přetížení přebírá BodyWriter
instanci k popisu textu zprávy. A BodyWriter
je abstraktní třída, která může být odvozena pro přizpůsobení způsobu vytváření těla zprávy. Můžete vytvořit vlastní BodyWriter
odvozenou třídu, která popisuje těla zpráv vlastním způsobem. Musíte přepsat metodu BodyWriter.OnWriteBodyContents
XmlDictionaryWriter, která přebírá ; tato metoda je zodpovědná za napsání těla.
Zapisovače textu lze ukládat do vyrovnávací paměti nebo ne vyrovnávací paměti (streamovat). Zapisovače těla ve vyrovnávací paměti můžou svůj obsah zapsat libovolný početkrát, zatímco streamované zapisují obsah pouze jednou. Vlastnost IsBuffered
označuje, zda je zapisovač těla uložen do vyrovnávací paměti, nebo ne. Můžete to nastavit pro zapisovač těla voláním chráněného BodyWriter
konstruktoru, který přebírá isBuffered
logický parametr. Zapisovače textu podporují vytvoření zapisovače těla ve vyrovnávací paměti z ne vyrovnávací paměti zapisovače těla. Můžete přepsat metodu OnCreateBufferedCopy
pro přizpůsobení tohoto procesu. Ve výchozím nastavení se používá vyrovnávací paměť v paměti, která obsahuje kód XML vrácený OnWriteBodyContents
. OnCreateBufferedCopy
přebírá celočíselnou hodnotu. Pokud tuto metodu maxBufferSize
přepíšete, nesmíte vytvářet vyrovnávací paměti větší než tato maximální velikost.
Třída BodyWriter
poskytuje WriteBodyContents
a CreateBufferedCopy
metody, které jsou v podstatě tenké obálky kolem OnWriteBodyContents
a OnCreateBufferedCopy
metody, v uvedeném pořadí. Tyto metody provádějí kontrolu stavu, aby se zajistilo, že se k zapisovači těla, který není uložen v vyrovnávací paměti, nemá přístup více než jednou. Tyto metody se volají přímo pouze při vytváření vlastních Message
odvozených tříd založených na BodyWriters
.
Vytváření chybových zpráv
K vytvoření chybových zpráv SOAP můžete použít určitá CreateMessage
přetížení. Nejzásadnější z nich je objekt MessageFault , který popisuje chybu. Další přetížení jsou k dispozici pro usnadnění. První takové přetížení vezme FaultCode
řetězec a důvod a vytvoří MessageFault
pomocí těchto informací použití MessageFault.CreateFault
. Druhé přetížení přebírá objekt podrobností a také ho předává společně CreateFault
s kódem chyby a důvodem. Například následující operace vrátí chybu.
public class MyService3 : IMyService
{
public Message GetData()
{
FaultCode fc = new FaultCode("Receiver");
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
return Message.CreateMessage(ver,fc,"Bad data","GetDataResponse");
}
public void PutData(Message m)
{
// Not implemented.
}
}
Public Class MyService3
Implements IMyService
Public Function GetData() As Message Implements IMyService.GetData
Dim fc As New FaultCode("Receiver")
Dim ver As MessageVersion = OperationContext.Current.IncomingMessageVersion
Return Message.CreateMessage(ver, fc, "Bad data", "GetDataResponse")
End Function
Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
End Sub
End Class
Extrahování dat textu zprávy
Třída Message
podporuje různé způsoby extrakce informací z jeho těla. Tyto kategorie je možné klasifikovat do následujících kategorií:
Získání celého textu zprávy napsaného najednou do zapisovače XML. To se označuje jako zápis zprávy.
Získání čtečky XML nad textem zprávy To vám umožní později získat přístup k části textu zprávy podle potřeby. To se označuje jako čtení zprávy.
Celá zpráva, včetně jejího textu, lze zkopírovat do vyrovnávací paměti MessageBuffer typu. To se označuje jako kopírování zprávy.
K textu Message
jen jednou se dostanete bez ohledu na to, jak se k němu přistupuje. Objekt zprávy má State
vlastnost, která je původně nastavena na Vytvořeno. Tři metody přístupu popsané v předchozím seznamu nastavují stav Napsaných, Read a Copied. Kromě toho Close
může metoda nastavit stav Uzavřeno, pokud už není potřeba obsah textu zprávy. Text zprávy je přístupný pouze ve stavu Vytvoření a neexistuje způsob, jak se po změně stavu vrátit zpět do stavu Vytvoření.
Psaní zpráv
Metoda WriteBodyContents(XmlDictionaryWriter) zapíše základní obsah dané Message
instance danému zapisovači XML. Metoda WriteBody dělá totéž, s tím rozdílem, že uzavře obsah těla do příslušného elementu obálky (napříkladsoap:body
<> ). WriteMessage Nakonec zapíše celou zprávu, včetně obtékání obálky SOAP a záhlaví. Pokud je protokol SOAP vypnutý (Version je MessageVersion.None), všechny tři metody dělají totéž: zapisují obsah textu zprávy.
Například následující kód zapíše text příchozí zprávy do souboru.
public class MyService4 : IMyService
{
public void PutData(Message m)
{
FileStream stream = new FileStream("myfile.xml",FileMode.Create);
XmlDictionaryWriter xdw =
XmlDictionaryWriter.CreateTextWriter(stream);
m.WriteBodyContents(xdw);
xdw.Flush();
}
public Message GetData()
{
throw new NotImplementedException();
}
}
Public Class MyService4
Implements IMyService
Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
Dim stream As New FileStream("myfile.xml", FileMode.Create)
Dim xdw As XmlDictionaryWriter = XmlDictionaryWriter.CreateTextWriter(stream)
m.WriteBodyContents(xdw)
xdw.Flush()
End Sub
Public Function GetData() As Message Implements IMyService.GetData
Throw New NotImplementedException()
End Function
End Class
Dvě další pomocné metody zapisuje určité značky elementů start PROTOKOLU SOAP. Tyto metody nemají přístup k textu zprávy, a proto nemění stav zprávy. Tady jsou některé z nich:
WriteStartBody zapíše počáteční základní prvek, například
<soap:Body>
.WriteStartEnvelope zapíše prvek počáteční obálky,
<soap:Envelope>
například .
Chcete-li napsat odpovídající značky koncových elementů, zavolejte WriteEndElement
odpovídající zapisovač XML. Tyto metody se zřídka volají přímo.
Čtení zpráv
Primárním způsobem čtení textu zprávy je volání GetReaderAtBodyContents. Vrátíte se zpátky XmlDictionaryReader , pomocí kterého si můžete přečíst text zprávy. Všimněte si, že Message přechody do stavu čtení ihned po GetReaderAtBodyContents zavolání, a ne při použití vrácené čtečky XML.
Metoda GetBody také umožňuje přístup k textu zprávy jako typ objektu. Interně tato metoda používá GetReaderAtBodyContents
a proto také přemístit stav zprávy do Read stavu (viz State vlastnost).
Je vhodné zkontrolovat IsEmpty vlastnost, v takovém případě je text zprávy prázdný a GetReaderAtBodyContents vyvolá chybu InvalidOperationException. Pokud se jedná o přijatou zprávu (například odpověď), můžete také zkontrolovat IsFault, což označuje, jestli zpráva obsahuje chybu.
Nejzákladnější přetížení GetBody deserializuje tělo zprávy do instance typu (označeného obecným parametrem) pomocí DataContractSerializer nakonfigurovaného s výchozím nastavením a se zakázanou kvótou MaxItemsInObjectGraph . Chcete-li použít jiný serializační modul nebo nakonfigurovat DataContractSerializer
jiným způsobem než výchozí, použijte GetBody přetížení, které přebírá XmlObjectSerializer.
Například následující kód extrahuje data z textu zprávy, která obsahuje serializovaný Person
objekt a vytiskne jméno osoby.
public class MyService5 : IMyService
{
public void PutData(Message m)
{
Person p = m.GetBody<Person>();
Console.WriteLine(p.name);
}
public Message GetData()
{
throw new NotImplementedException();
}
}
}
namespace Samples2
{
[ServiceContract]
public interface IMyService
{
[OperationContract]
Message GetData();
[OperationContract]
void PutData(Message m);
}
[DataContract]
public class Person
{
[DataMember] public string name;
[DataMember] public int age;
}
Public Class MyService5
Implements IMyService
Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
Dim p As Person = m.GetBody(Of Person)()
Console.WriteLine(p.name)
End Sub
Public Function GetData() As Message Implements IMyService.GetData
Throw New NotImplementedException()
End Function
End Class
End Namespace
Namespace Samples2
<ServiceContract()> _
Public Interface IMyService
<OperationContract()> _
Function GetData() As Message
<OperationContract()> _
Sub PutData(ByVal m As Message)
End Interface
<DataContract()> _
Public Class Person
<DataMember()> _
Public name As String
<DataMember()> _
Public age As Integer
End Class
Kopírování zprávy do vyrovnávací paměti
Někdy je nutné získat přístup k textu zprávy více než jednou, například pro přeposlání stejné zprávy do více cílů jako součást systému pro předplatitele vydavatele. V tomto případě je nutné ukládat do vyrovnávací paměti celou zprávu (včetně těla). Můžete to udělat voláním CreateBufferedCopy(Int32). Tato metoda přebírá celočíselná parametr, který představuje maximální velikost vyrovnávací paměti a vytvoří vyrovnávací paměť, která není větší než tato velikost. Pokud zpráva pochází z nedůvěryhodného zdroje, je důležité ji nastavit na bezpečnou hodnotu.
Vyrovnávací paměť se vrátí jako MessageBuffer instance. K datům ve vyrovnávací paměti můžete přistupovat několika způsoby. Primárním způsobem je volat CreateMessage vytváření Message
instancí z vyrovnávací paměti.
Dalším způsobem, jak získat přístup k datům ve vyrovnávací paměti, je implementovat IXPathNavigable rozhraní, které MessageBuffer třída implementuje pro přímý přístup k podkladovému XML. Některá CreateNavigator přetížení umožňují vytvářet System.Xml.XPath navigátory chráněné kvótou uzlů, což omezuje počet uzlů, které je možné navštívit. To pomáhá zabránit útokům na dostupnost služby na základě dlouhé doby zpracování. Tato uvozovka je ve výchozím nastavení zakázaná. Některá CreateNavigator
přetížení umožňují určit, jak se má prázdné znaky zpracovávat v JAZYCE XML pomocí výčtu XmlSpace s výchozím nastavením XmlSpace.None
.
Posledním způsobem, jak získat přístup k obsahu vyrovnávací paměti zprávy, je zapsat jeho obsah do datového proudu pomocí WriteMessage.
Následující příklad ukazuje proces práce s MessageBuffer
: příchozí zpráva se přepošla více příjemcům a pak se protokoluje do souboru. Bez ukládání do vyrovnávací paměti to není možné, protože text zprávy je pak přístupný pouze jednou.
[ServiceContract]
public class ForwardingService
{
private List<IOutputChannel> forwardingAddresses;
[OperationContract]
public void ForwardMessage (Message m)
{
//Copy the message to a buffer.
MessageBuffer mb = m.CreateBufferedCopy(65536);
//Forward to multiple recipients.
foreach (IOutputChannel channel in forwardingAddresses)
{
Message copy = mb.CreateMessage();
channel.Send(copy);
}
//Log to a file.
FileStream stream = new FileStream("log.xml",FileMode.Append);
mb.WriteMessage(stream);
stream.Flush();
}
}
<ServiceContract()> _
Public Class ForwardingService
Private forwardingAddresses As List(Of IOutputChannel)
<OperationContract()> _
Public Sub ForwardMessage(ByVal m As Message)
'Copy the message to a buffer.
Dim mb As MessageBuffer = m.CreateBufferedCopy(65536)
'Forward to multiple recipients.
Dim channel As IOutputChannel
For Each channel In forwardingAddresses
Dim copy As Message = mb.CreateMessage()
channel.Send(copy)
Next channel
'Log to a file.
Dim stream As New FileStream("log.xml", FileMode.Append)
mb.WriteMessage(stream)
stream.Flush()
End Sub
End Class
Třída MessageBuffer
má další členy, které stojí za zmínku. Metodu Close lze volat k uvolnění prostředků, pokud už není potřeba obsah vyrovnávací paměti. Vlastnost BufferSize vrátí velikost přidělené vyrovnávací paměti. Vlastnost MessageContentType vrátí typ obsahu MIME zprávy.
Přístup k textu zprávy pro ladění
Pro účely ladění můžete volat metodu ToString , která získá reprezentaci zprávy jako řetězec. Tato reprezentace obecně odpovídá způsobu, jakým by zpráva vypadala na drátu, pokud by byla kódována pomocí textového kodéru, s tím rozdílem, že XML by byl lépe naformátovaný pro čitelnost člověka. Jedinou výjimkou je text zprávy. Tělo může být přečteno pouze jednou a ToString
nezmění stav zprávy. ToString
Proto metoda nemusí mít přístup k textu a může nahradit zástupný symbol (například "..." nebo tři tečky) místo textu zprávy. Proto nepoužívejte ToString
k protokolování zpráv, pokud je důležitý základní obsah zpráv.
Přístup k jiným částem zpráv
Různé vlastnosti jsou k dispozici pro přístup k informacím o jiné zprávě, než je její základní obsah. Po zavření zprávy se ale nedají volat:
Vlastnost Headers představuje záhlaví zprávy. Podívejte se na část Práce se záhlavími dále v tomto tématu.
Vlastnost Properties představuje vlastnosti zprávy, které jsou části pojmenovaných dat připojené ke zprávě, které se obvykle nevygenerují při odeslání zprávy. Viz část "Práce s vlastnostmi" dále v tomto tématu.
Tato Version vlastnost označuje verzi SOAP a WS-Adresování přidruženou ke zprávě nebo
None
pokud je protokol SOAP zakázán.Tato IsFault vlastnost se vrátí
true
, pokud je zpráva chybovou zprávou SOAP.Vlastnost IsEmpty vrátí
true
, pokud je zpráva prázdná.
Tuto metodu GetBodyAttribute(String, String) můžete použít pro přístup ke konkrétnímu atributu elementu body wrapper (například <soap:Body>
) identifikovaného konkrétním názvem a oborem názvů. Pokud se takový atribut nenajde, null
vrátí se. Tuto metodu lze volat pouze v případě Message
, že je ve stavu Vytvoření (pokud text zprávy ještě nebyl přístup).
Práce se záhlavími
A Message
může obsahovat libovolný počet pojmenovaných fragmentů XML, označovaných jako záhlaví. Každý fragment se obvykle mapuje na hlavičku SOAP. Hlavičky jsou přístupné prostřednictvím Headers
vlastnosti typu MessageHeaders. MessageHeaders je kolekce MessageHeaderInfo objektů a jednotlivé hlavičky lze získat přístup prostřednictvím jeho IEnumerable rozhraní nebo prostřednictvím indexeru. Například následující kód uvádí názvy všech hlaviček v souboru Message
.
public class MyService6 : IMyService
{
public void PutData(Message m)
{
foreach (MessageHeaderInfo mhi in m.Headers)
{
Console.WriteLine(mhi.Name);
}
}
public Message GetData()
{
throw new NotImplementedException();
}
}
Public Class MyService6
Implements IMyService
Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
Dim mhi As MessageHeaderInfo
For Each mhi In m.Headers
Console.WriteLine(mhi.Name)
Next mhi
End Sub
Public Function GetData() As Message Implements IMyService.GetData
Throw New NotImplementedException()
End Function
End Class
Přidávání, odebírání a hledání hlaviček
Novou hlavičku můžete přidat na konec všech existujících hlaviček pomocí Add metody. Metodu Insert můžete použít k vložení hlavičky do určitého indexu. Existující záhlaví se posunou pro vloženou položku. Záhlaví jsou seřazená podle indexu a první dostupný index je 0. Pomocí různých CopyHeadersFrom přetížení metod můžete přidat hlavičky z jiné Message
nebo MessageHeaders
instance. Některá přetížení kopírují jednu jednotlivou hlavičku, zatímco jiné kopírují všechny. Metoda Clear odebere všechny hlavičky. Metoda RemoveAt odebere záhlaví v určitém indexu (posune všechna záhlaví za ním). Metoda RemoveAll odebere všechny hlavičky s konkrétním názvem a oborem názvů.
Načtěte konkrétní hlavičku FindHeader pomocí metody. Tato metoda vezme název a obor názvů hlavičky k vyhledání a vrátí jeho index. Pokud se záhlaví vyskytuje více než jednou, vyvolá se výjimka. Pokud se hlavička nenajde, vrátí hodnotu -1.
V modelu hlaviček PROTOKOLU SOAP můžou mít Actor
hlavičky hodnotu, která určuje zamýšlený příjemce hlavičky. Nejzásadnější FindHeader
přetížení hledá pouze hlavičky určené pro konečný příjemce zprávy. Jiné přetížení však umožňuje určit, které Actor
hodnoty jsou zahrnuty do vyhledávání. Další informace najdete ve specifikaci PROTOKOLU SOAP.
Metoda CopyTo(MessageHeaderInfo[], Int32) je poskytována ke kopírování hlaviček z MessageHeaders kolekce do pole MessageHeaderInfo objektů.
Pokud chcete získat přístup k datům XML v hlavičce, můžete volat GetReaderAtHeader a vracet čtečku XML pro konkrétní index záhlaví. Chcete-li deserializovat obsah záhlaví do objektu, použijte GetHeader<T>(Int32) nebo jeden z dalších přetížení. Nejzásadnější přetížení deserializovat hlavičky pomocí DataContractSerializer nakonfigurovaného výchozího způsobu. Chcete-li použít jiný serializátor nebo jinou konfiguraci DataContractSerializer
, použijte jedno z přetížení, které přebírají XmlObjectSerializer
. Existují také přetížení, která přebírají název hlavičky, obor názvů a volitelně seznam Actor
hodnot místo indexu; jedná se o kombinaci FindHeader
a GetHeader
.
Práce s vlastnostmi
Instance Message
může obsahovat libovolný počet pojmenovaných objektů libovolných typů. Tato kolekce je přístupná prostřednictvím Properties
vlastnosti typu MessageProperties
. Kolekce implementuje IDictionary<TKey,TValue> rozhraní a funguje jako mapování z String na Object. Hodnoty vlastností se obvykle nemapují přímo na žádnou část zprávy v drátě, ale spíše poskytují různé rady zpracování zpráv pro různé kanály v zásobníku kanálu WCF nebo na CopyTo(MessageHeaderInfo[], Int32) rozhraní služby. Příklad najdete v tématu Přehled architektury přenosu dat.
Dědění z třídy zprávy
Pokud předdefinované typy zpráv vytvořené pomocí CreateMessage
nesplňují vaše požadavky, vytvořte třídu odvozenou od Message
třídy.
Definování obsahu textu zprávy
Existují tři hlavní techniky pro přístup k datům v textu zprávy: zápis, čtení a kopírování do vyrovnávací paměti. Tyto operace nakonec vedou k OnWriteBodyContentsvolání , OnGetReaderAtBodyContentsa OnCreateBufferedCopy metody , v uvedeném pořadí, na odvozené třídě Message
. Základní Message
třída zaručuje, že pro každou Message
instanci je volána pouze jedna z těchto metod a že není volána více než jednou. Základní třída také zajišťuje, že metody nejsou volány na uzavřenou zprávu. Ve vaší implementaci není nutné sledovat stav zprávy.
OnWriteBodyContents je abstraktní metoda a musí být implementována. Nejzásadnější způsob, jak definovat obsah zprávy, je psát pomocí této metody. Například následující zpráva obsahuje 100 000 náhodných čísel od 1 do 20.
public class RandomMessage : Message
{
override protected void OnWriteBodyContents(XmlDictionaryWriter writer)
{
Random r = new Random();
for (int i = 0; i <100000; i++)
{
writer.WriteStartElement("number");
writer.WriteValue(r.Next(1,20));
writer.WriteEndElement();
}
}
//code omitted…
Public Class RandomMessage
Inherits Message
Protected Overrides Sub OnWriteBodyContents( _
ByVal writer As XmlDictionaryWriter)
Dim r As New Random()
Dim i As Integer
For i = 0 To 99999
writer.WriteStartElement("number")
writer.WriteValue(r.Next(1, 20))
writer.WriteEndElement()
Next i
End Sub
' Code omitted.
Ve většině případů mají výchozí OnGetReaderAtBodyContents() implementace, OnCreateBufferedCopy které fungují. Výchozí volání OnWriteBodyContentsimplementace , uložení výsledků do vyrovnávací paměti a práce s výslednou vyrovnávací pamětí. V některých případech to ale nemusí stačit. Čtení zprávy v předchozím příkladu vede k ukládání do vyrovnávací paměti 100 000 elementů XML, což nemusí být žádoucí. Můžete chtít přepsat OnGetReaderAtBodyContents() vrácení vlastní XmlDictionaryReader odvozené třídy, která obsluhuje náhodná čísla. Potom můžete přepsat OnWriteBodyContents použití čtečky, kterou OnGetReaderAtBodyContents() metoda vrátí, jak je znázorněno v následujícím příkladu.
public override MessageHeaders Headers
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override MessageProperties Properties
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override MessageVersion Version
{
get { throw new Exception("The method or operation is not implemented."); }
}
}
public class RandomMessage2 : Message
{
override protected XmlDictionaryReader OnGetReaderAtBodyContents()
{
return new RandomNumbersXmlReader();
}
override protected void OnWriteBodyContents(XmlDictionaryWriter writer)
{
XmlDictionaryReader xdr = OnGetReaderAtBodyContents();
writer.WriteNode(xdr, true);
}
public override MessageHeaders Headers
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override MessageProperties Properties
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override MessageVersion Version
{
get { throw new Exception("The method or operation is not implemented."); }
}
}
public class RandomNumbersXmlReader : XmlDictionaryReader
{
//code to serve up 100000 random numbers in XML form omitted…
Public Overrides ReadOnly Property Headers() As MessageHeaders
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
Public Overrides ReadOnly Property Properties() As MessageProperties
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
Public Overrides ReadOnly Property Version() As MessageVersion
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
End Class
Public Class RandomMessage2
Inherits Message
Protected Overrides Function OnGetReaderAtBodyContents() As XmlDictionaryReader
Return New RandomNumbersXmlReader()
End Function
Protected Overrides Sub OnWriteBodyContents(ByVal writer As XmlDictionaryWriter)
Dim xdr As XmlDictionaryReader = OnGetReaderAtBodyContents()
writer.WriteNode(xdr, True)
End Sub
Public Overrides ReadOnly Property Headers() As MessageHeaders
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
Public Overrides ReadOnly Property Properties() As MessageProperties
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
Public Overrides ReadOnly Property Version() As MessageVersion
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
End Class
Public Class RandomNumbersXmlReader
Inherits XmlDictionaryReader
'code to serve up 100000 random numbers in XML form omitted
Podobně můžete chtít přepsat OnCreateBufferedCopy
, aby se vrátila vlastní MessageBuffer
odvozená třída.
Kromě poskytování obsahu zprávy musí odvozená třída zprávy také přepsat Version
, Headers
a Properties
vlastnosti.
Všimněte si, že pokud vytvoříte kopii zprávy, použije kopie záhlaví zprávy z originálu.
Ostatní členové, kteří je možné přepsat
Můžete přepsat OnWriteStartEnvelope, OnWriteStartHeadersa OnWriteStartBody metody určit, jak se obálka SOAP, hlavičky SOAP a základní značky SOAP elementu zapisují značky. Ty obvykle odpovídají <soap:Envelope>
, <soap:Header>
a <soap:Body>
. Tyto metody by obvykle neměly zapsat nic, pokud Version vlastnost vrátí None.
Poznámka:
Výchozí implementace OnGetReaderAtBodyContents
volání OnWriteStartEnvelope
a OnWriteStartBody
před voláním OnWriteBodyContents
a uložením výsledků do vyrovnávací paměti. Hlavičky se nezapisují.
Přepište metodu OnWriteMessage , která změní způsob, jakým je celá zpráva vytvořena z různých částí. Metoda OnWriteMessage
je volána z WriteMessage a z výchozí OnCreateBufferedCopy implementace. Upozorňujeme, že přepsání WriteMessage není osvědčeným postupem. Je lepší přepsat vhodné On
metody (například OnWriteStartEnvelope, OnWriteStartHeaders, a OnWriteBodyContents.
Přepsáním OnBodyToString můžete přepsat způsob znázornění textu zprávy během ladění. Výchozí hodnota je reprezentovat jako tři tečky (...). Všimněte si, že tuto metodu lze volat vícekrát, pokud je stav zprávy cokoli jiného než Uzavřeno. Implementace této metody by nikdy neměla způsobit žádnou akci, která musí být provedena pouze jednou (například čtení z dopředného datového proudu).
Přepište metodu OnGetBodyAttribute tak, aby byl povolen přístup k atributům v elementu těla SOAP. Tuto metodu lze volat libovolný počet, ale Message
základní typ zaručuje, že je volána pouze v případě, že zpráva je ve stavu Vytvoření. Není nutné kontrolovat stav v implementaci. Výchozí implementace vždy vrátí null
, což označuje, že neexistují žádné atributy v elementu body.
Pokud objekt Message
musí provést jakékoli zvláštní vyčištění, pokud už text zprávy není vyžadován, můžete přepsat OnClose. Výchozí implementace nic nedělá.
Vlastnosti IsEmpty
a IsFault
vlastnosti lze přepsat. Ve výchozím nastavení vrátí obě hodnoty false
.