Fun with SOAP Extensions

Note As promised, in this month's column we're going to look at one of the more advanced, but cooler features of ASP.NET Web Services—SOAP Extensions. For this month's column Keith Ballinger, a Program Manager for .NET Web Services, has offered to share some of his knowledge of this subject. Thanks and see you next month. -Rob

One of the more interesting things you can do with the .NET Framework Web services technology is create SOAP Extensions. These extensions allow you to gain access to the actual network stream before it is deserialized into objects within the framework, and vice versa.

SOAP Extensions allow developers to create very interesting applications on top of the core SOAP architecture found within .NET. For instance, you can implement an encryption algorithm on top of the Web Service call. Alternatively, you could implement a compression routine, or even create a SOAP Extension that will accept SOAP Attachments.

How does this work? It's easy. First, I'd recommend that you review Rob Howard's earlier article Web Services with ASP.NET and then come back.

Basically, you need to do two things:

Create a class that derives from System.Web.Services.Protocols.SoapExtension

Create a class that derives from System.Web.Services.Protocols.SoapExtensionAttribute

And you are almost done! Now, all that you have to do is create something interesting from you derived classes. Ok, so maybe that isn't as easy as I make it sound. (Creating the interesting part is almost always the hardest part of development, isn't it?)

For this column, we will create an extension that records incoming and outgoing SOAP messages to our Web Service. This trace extension is useful for debugging when you really care about getting the SOAP message to look exactly the way you want it to look.

The core piece of implementation you need to worry about is the ProcessMessage method. This method is called several times, and every time it sends a SoapMessage object, it includes information on the stage of the SOAP message. To illustrate, let's examine the flow of a SOAP message within a Web Service. All of this applies on the client as well as the server, but we will concentrate on the server for this example.

A SOAP message comes in and the server figures out which method to route to.

Then the server checks to see if any SOAP extensions (that's us!) should be invoked, and if so, invokes them with the BeforeDeserialize event stage.

Last, the server deserializes the stream and invokes all the extensions for the AfterDeserialize stage.

The key for us here is the BeforeDeserialize event stage. Here, we grab the stream and write it out to the log file:

Notice we also write it out to a MemoryStream so that the SoapMessage object still has a valid stream when we are done. If we don't do this, the server will try to deserialize the network stream that was originally on the SoapMessage, and find nothing there.

A similar process takes place when we log the SOAP message that the server will return to the client. However, there is one exception. In the BeforeSerialize stage, we need to swap out the network stream on the SoapMessage, and replace it with one of our own MemoryStreams. This slight of hand will allow us to record whatever is sent as SOAP, without immediately losing it in the network.

Notice that we record whatever was written to the memory stream, and then write it out to the network stream once we are done. If we don't write it out to the stream we stole, the client will never get a response.

So there you have it—a trace extension. SOAP Extensions are a very useful feature, and I hope to see a lot imaginative uses for them over the next few years. There are some slight, but fundamental changes to the way extensions work in the upcoming beta 2 of the .NET Framework, but don't worry, we'll update this code (which is for beta 1) with beta 2 code when it comes out.

Show:
Inherited
Protected

Was this page helpful?

Your feedback about this content is important.Let us know what you think.