
*Moved to: http://fluentbytes.com/applying-soap-extension-client-proxy-without-altering-generated-proxy-code/
Today I have been working on a web service that needed to accept an additional SOAP header, but I did not want to give the client developers the additional burden of actually specifying the header before they could call the web service. I just wanted it to be infrastructural and not something the developers need to worry about.
Now there are quite some nice parts in the .NET framework that help you with defining a custom SOAP header. To make a generated proxy to add the header automatically I thought it would be a good idea to add a SOAP extension to the application that could handle this at the client side. But that appeared to be more troublesome then I anticipated.
The problem I ran into was that you need to apply a SoapExtensionAttribute to every method on the proxy that needs to go through your handler. That would not be a problem if Microsoft had done a better job in the way they generate the proxy class. The generated class does not mark the methods as virtual, therefore you are not able to derive from the class and apply your attributes there. You are forced to alter the generated code. That is something I just refused to do.
It turned out that you can in fact apply the SOAP extension to every SOAP call you make by adding a section to your application configuration file, but my client also serves as web service making incoming calls also to go through the extension.
By adding the extension to your web.config file you are able to enable the SOAP extension for all the calls, but I needed to differentiate between incoming calls and outgoing calls. Only the outgoing calls needed the additional header. The solution to the problem appears to be remarkably simple, but nobody on the forums provided this solution, as far as Google would tell me J
What I did is to implement the ProcessMessage call to test if the incoming call is of the type SoapClientMessage. If that is the case, I know it’s an outbound call, if it’s of the type SoapServerMessage I know it’s an incoming call. The implementation looks now something like this:
You add the following to your web.config or app.config file:
<webServices>
<soapExtensionTypes>
<addtype=“mySoapExtensionType,MySoapExtensionAssemblyName“/>
</soapExtensionTypes>
</webServices>
You implement the Soapextension to process the message as follows:
public override void ProcessMessage(SoapMessage message)
{
if (message is SoapClientMessage)
{
if (message.Stage == SoapMessageStage.BeforeSerialize)
{
message.Headers.Add(MyCustomHeaderInstance);
}
}
}
You see it’s remarkably easy to determine incoming and outgoing calls and this leaves you from the burden to alter the generated code to apply the extension to your outgoing calls.
2 comments
I don’t know if you are using the WSE framework for development but SoapInput/Output filters are much prettier and can also be used on WSE soapservices. I think that SoapExtensions can only be used on .net webservices.
Ramon Smits
Thanks for your response 🙂
We have the explicit restriction not to use WSE yet. This is because we want to transition to WCF as soon as possible. Therefore we restricted the project not to introduce any more API’s then the default .NET Framework. When we transition to WCF, we will be fixing these kinds of infrastructural things with out of the box WCF functionality. B.T.W. the Soap Extension can only be used on the .NET platform, because these are defined as extensibility mechanism of asmx web services. The fact that we add the custom SOAP header does not mean we would not be interoperable, since the SOAP headers are defined well in terms of interop. The fact if I used WSE, SOAP extension of any other means, would not interfere with this interoperability, because we adhere to the SOAP standards as defined. WSE itself uses SOAP extensions to implement the WS-* protocols. So using WSE here would not have solved my problem differently then I described here I think.
marcel de Vries