Mark Wilson I am the creator of TopXML. I am available for international and local (Australia) contracts. I am a Solution Architect/Business Analyst. I have worked in IT in several countries (NZ, Australia, South Africa, UK) building and training teams for government and very large non-governmental organizations. I am ex-Microsoft Consulting Services. I wrote the first book on Microsoft XML published in 2000 called XML Programming with VB and ASP. Most recently I have been building tools for the SEO industry. Ask me for a 37 point SEO health-checkup for your website.
First posted :
03/24/2008
Times viewed :
281
ISoapMessage Message Headers
Accessing header entries in RPC messages works just the opposite
way of adding them. The SoapFormatter’s
stores the headers it found in the processed message in the Headers property of
the object assigned to the TopObject
property. That is all there is to reading headers from an RPC message.
We can re-use the HeaderProcessor class we wrote in the previous chapter
to process header entries from RPC messages when we extend our example to act
on message headers. All we need to do is to extract them from the SoapMessage and
pass them off to the processor object.
One possible place to add this functionality is in the SoapMessageReceiver’s
ProcessSoapStream()
method, just before we pass the SoapMessage to the stub. Processing headers there allows
us to can skip invoking the server method when a message header indicates that
the message is not intended for us. The modified method is shown in the listing
below. In some applications it may make more sense to have the stub object process
the SOAP headers, but let’s not argue this here.
Listing Processing message headers from RPC messages
public new void ProcessSoapStream( Stream stream )
{
try
{
SoapMessage msg = new
SoapMessage();
_Formatter.TopObject =
msg; | #1
_Formatter.Deserialize( stream );
|
HeaderProcessor
processor = new HeaderProcessor(); |#2
processor.HandleHeaders( msg.Headers ); |
_Stub.DispatchMessage(
msg ); |
}
catch(HeaderException ex)
{
Console.WriteLine( "Incompatible Headers:" );
Console.WriteLine( ex.Message );
}
} // ProcessSoapStream()
(annotation) <#1
Deserialize the RPC message .>
(annotation) <#2 The Headers property contains the
header entries of a deserialized RPC message.>
Do you remember how we can register a HeaderHandler to process headers when
call Deserialize()
from the last chapter? We learned this technique to retrieve headers in section
13.3.4.3. Registering a handler can save us some unnecessary processing because
the SoapFormatter
calls the handler before it deserializes the complete message. When we detect
from the headers that the message is not intended for us, we can stop
processing the message right there.
If you remember, we ran into some problems deserializing objects
and registering a HeaderHandler
at the same time, because we could not determine the type of the serialized
object. For with RPC messages we do not have to determine the type because the
entry describes the method call. We still have to set up the object to return
from Deserialize()
manually, but we know that the caller always expects an object that implements
the ISoapMessage
interface. Ideally we would return a SoapMessage object, but SoapMessage does
not implement ISerializable.
However, we can derive a class from SoapMessage and implement ISerializable
there. Then we can return such an object directly from the HeaderHandler
method populate it in the deserialization constructor just as if the HeaderHandler
was never in the picture.