I have a C#/.Net 1.1 client talking to a Java based web service. I need to
insert a soap header on the client side which is expected on the server side.
Currently, the Java ws provider, Axis, does not support automatic wsdl
generation of custom headers so the wsdl has no information regarding the
required header.
I've read through a lot of material and managed to get a workable solution
but it is far from ideal.
I created a new AuthHeader:SoapHeader class and updated the client ws proxy
to make use of the new header. This worked but I want to avoid having to
modify tool generated code. I don't want to touch the .Net wsdl.exe
generated ws proxy.
One other solution may be to modify the stream via my own SoapExtension
class. Problem is that requires working at a low level on the stream. Why
should I have to do that when .Net provides a rich SOAP API?
I would think I should be able to simply insert my own SoapHeader into the
SoapMessage via SoapExtension.ProcessMessage(). I have tried this approach
without success. I get a System.InvalidOperationException upon attempted
serialization of the SoapMessage. The error is, "The type
SimpleWSClient.AuthHeader was not expected. Use the XmlInclude or SoapInclude
attribute to specify types that are not known statically." It seems like
this approach should work. I assumed that a SoapHeader object would already
know how to serialize itself if it contains only basic types.
My SoapHeader and SoapExtension classes below:
using System;
using System.Xml.Serialization;
using System.Web.Services.Protocols;
namespace SimpleWSClient
{
public class AuthHeader : SoapHeader
{
private string userName;
private string password;
public AuthHeader()
{
}
public AuthHeader(string user, string pwd)
{
UserName = user;
Password = pwd;
}
public string UserName
{
get { return userName; }
set { userName = value; }
}
public string Password
{
get { return password; }
set { password = value; }
}
}
}
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml;
using System.Xml.Serialization;
namespace SimpleWSClient
{
/// <summary>
/// SOAP Extension that checks the SOAP Header for a username and password
/// and does the necessary authentication and authorization.
/// </summary>
public class UsernamePasswordSoapExtension : SoapExtension
{
public override object GetInitializer( Type serviceType )
{
return null;
}
public override object GetInitializer( LogicalMethodInfo methodInfo,
SoapExtensionAttribute attribute )
{
return null;
}
public override void Initialize( object initializer )
{
}
public override void ProcessMessage( SoapMessage message )
{
if (message.Stage == SoapMessageStage.BeforeSerialize)
{
SecurityContext context = SecurityContext.getInstance();
AuthHeader soapHeader = new AuthHeader(context.UserName,
context.Password);
SoapClientMessage scm = (SoapClientMessage)message;
SoapHeaderCollection headers = scm.Headers;
headers.Add(soapHeader);
}
}
}
}
This last approach is what I am after. It would allow me to insert a custom
SoapHeader using a high-level Soap API without having to inject custom code
into a tool generated ws proxy.
Is it possible to make this last approach work or am I forced to work with
the first two options?
Thanks.