473,573 Members | 2,922 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Inserting a SOAP Header in a client request

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:Soap Header 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.P rocessMessage() . I have tried this approach
without success. I get a System.InvalidO perationExcepti on 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.Seri alization;
using System.Web.Serv ices.Protocols;

namespace SimpleWSClient
{
public class AuthHeader : SoapHeader
{
private string userName;
private string password;

public AuthHeader()
{
}

public AuthHeader(stri ng 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.Serv ices;
using System.Web.Serv ices.Protocols;
using System.Xml;
using System.Xml.Seri alization;

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 UsernamePasswor dSoapExtension : SoapExtension
{

public override object GetInitializer( Type serviceType )
{
return null;
}

public override object GetInitializer( LogicalMethodIn fo methodInfo,
SoapExtensionAt tribute attribute )
{
return null;
}

public override void Initialize( object initializer )
{
}

public override void ProcessMessage( SoapMessage message )
{
if (message.Stage == SoapMessageStag e.BeforeSeriali ze)
{
SecurityContext context = SecurityContext .getInstance();
AuthHeader soapHeader = new AuthHeader(cont ext.UserName,
context.Passwor d);
SoapClientMessa ge scm = (SoapClientMess age)message;
SoapHeaderColle ction headers = scm.Headers;
headers.Add(soa pHeader);
}
}

}
}
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.
Nov 23 '05 #1
6 20235
Hello john,
I dont see the difference in what you call the second option and the
third option. What you seem to be missing is overriding the chain stream
and writing to the stream (which I gather you dont wish to do). The problem
with your code is .. yes you're using the soap object model to add the header
but you've failed to modify the stream by writing that information back into
the stream. Also have you considered using WSE? and also are you sure the
java service is not using WS-Security? If it is, you would need to send standard
username tokens as opposed to a custom auth header

HTH
Regards,
Dilip Krishnan
MCAD, MCSD.net
dkrishnan at geniant dot com
http://www.geniant.com
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:Soap Header 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.P rocessMessage() . I have tried this
approach without success. I get a System.InvalidO perationExcepti on
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.Seri alization;
using System.Web.Serv ices.Protocols;
namespace SimpleWSClient
{
public class AuthHeader : SoapHeader
{
private string userName;
private string password;
public AuthHeader()
{
}
public AuthHeader(stri ng 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.Serv ices;
using System.Web.Serv ices.Protocols;
using System.Xml;
using System.Xml.Seri alization;
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 UsernamePasswor dSoapExtension : SoapExtension
{
public override object GetInitializer( Type serviceType )
{
return null;
}
public override object GetInitializer( LogicalMethodIn fo methodInfo,
SoapExtensionAt tribute attribute )
{
return null;
}
public override void Initialize( object initializer )
{
}
public override void ProcessMessage( SoapMessage message )
{
if (message.Stage == SoapMessageStag e.BeforeSeriali ze)
{
SecurityContext context = SecurityContext .getInstance();
AuthHeader soapHeader = new AuthHeader(cont ext.UserName,
context.Passwor d);
SoapClientMessa ge scm = (SoapClientMess age)message;
SoapHeaderColle ction headers = scm.Headers;
headers.Add(soa pHeader);
}
}
}
}
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.

Nov 23 '05 #2
Sorry if my original post was not clear. Let me clarify the options I was
exploring:

Option 1: custom SoapHeader and modify the ws client proxy by hand to
reference the new SoapHeader..

Option 2: custom SoapExtension and modify the stream by hand via
ChainStream().

Option 3: custom Soap Extension and SoapHeader and modify the SoapMessage
via ProcessMessage( ).

So, it sounds like option 3 is not really an option. Option 2 means working
with a byte stream instead of a Soap API. ChainStream() is the only place we
can modify the message before serialization? I guess I'm still not quite
clear on the distinction between ChainStream() and ProcessMessage( ).

Given that this is all in the context of a web service request, I shouldn't
have to work at the byte level to add a soap header to a soap message. I
imagine the Stream could somehow be converted to a SoapMessage before adding
the soap header but that would be inefficient given that it will be converted
into a SoapMessage later in the call chain.

WSE is something I will explore but for the time being this is what I am
working with. I need to research Axis 1.1 support of WS-Security and compare
it to .Net.
The server side of this solution already exists and works for a different
client implementation.

Clean insertion of a custom soap header on the client side should be
relatively painless. This is how it's done in Axis (Java):

// setup authorization header
SOAPHeaderEleme nt authHeader = new SOAPHeaderEleme nt( "",
"AuthHeader " );
MessageElement usernameElement = ( MessageElement )
authHeader.addC hildElement( "UserName" );
MessageElement passwordElement = ( MessageElement )
authHeader.addC hildElement( "Password" );
usernameElement .setObjectValue ("jdoe");
passwordElement .setObjectValue ("password") ;
call.addHeader( authHeader );

John

"Dilip Krishnan" wrote:
Hello john,
I dont see the difference in what you call the second option and the
third option. What you seem to be missing is overriding the chain stream
and writing to the stream (which I gather you dont wish to do). The problem
with your code is .. yes you're using the soap object model to add the header
but you've failed to modify the stream by writing that information back into
the stream. Also have you considered using WSE? and also are you sure the
java service is not using WS-Security? If it is, you would need to send standard
username tokens as opposed to a custom auth header

HTH
Regards,
Dilip Krishnan
MCAD, MCSD.net
dkrishnan at geniant dot com
http://www.geniant.com


Nov 23 '05 #3
I reviewed the article, "Altering the SOAP Message Using SOAP Extensions". I
see that update of the soap message requires overrides in both ChainStream()
and ProcessMessage( ).

What I don't understand is why I'm not able to update the soap message via
the SoapMessage API. ProcessMessage( ) is passed a SoapMessage object but it
can't be directly updated, I am forced to update a byte stream instead.
SoapExtension inherits from System.Object so I'm puzzled why updates are only
allowed via a byte stream.

Are there any other options?
Nov 23 '05 #4
Hello john,
You really dont have to play around with bits and bytes. Every Soap based
Object has a LoadXml and GetXml that you can use in conjunction with a XmlTextReader/Writer.
So all you need to do is write to the chained stream using an xml writer.
But u do have to chain the stream to be able to alter the stream
HTH
Regards,
Dilip Krishnan
MCAD, MCSD.net
dkrishnan at geniant dot com
http://www.geniant.com
Sorry if my original post was not clear. Let me clarify the options I
was exploring:

Option 1: custom SoapHeader and modify the ws client proxy by hand to
reference the new SoapHeader..

Option 2: custom SoapExtension and modify the stream by hand via
ChainStream().

Option 3: custom Soap Extension and SoapHeader and modify the
SoapMessage via ProcessMessage( ).

So, it sounds like option 3 is not really an option. Option 2 means
working with a byte stream instead of a Soap API. ChainStream() is
the only place we can modify the message before serialization? I
guess I'm still not quite clear on the distinction between
ChainStream() and ProcessMessage( ).

Given that this is all in the context of a web service request, I
shouldn't have to work at the byte level to add a soap header to a
soap message. I imagine the Stream could somehow be converted to a
SoapMessage before adding the soap header but that would be
inefficient given that it will be converted into a SoapMessage later
in the call chain.

WSE is something I will explore but for the time being this is what I
am
working with. I need to research Axis 1.1 support of WS-Security and
compare
it to .Net.
The server side of this solution already exists and works for a
different
client implementation.
Clean insertion of a custom soap header on the client side should be
relatively painless. This is how it's done in Axis (Java):

// setup authorization header
SOAPHeaderEleme nt authHeader = new SOAPHeaderEleme nt( "",
"AuthHeader " );
MessageElement usernameElement = ( MessageElement )
authHeader.addC hildElement( "UserName" );
MessageElement passwordElement = ( MessageElement )
authHeader.addC hildElement( "Password" );
usernameElement .setObjectValue ("jdoe");
passwordElement .setObjectValue ("password") ;
call.addHeader( authHeader );
John

"Dilip Krishnan" wrote:
Hello john,
I dont see the difference in what you call the second option and the
third option. What you seem to be missing is overriding the chain
stream
and writing to the stream (which I gather you dont wish to do). The
problem
with your code is .. yes you're using the soap object model to add
the header
but you've failed to modify the stream by writing that information
back into
the stream. Also have you considered using WSE? and also are you sure
the
java service is not using WS-Security? If it is, you would need to
send standard
username tokens as opposed to a custom auth header
HTH
Regards,
Dilip Krishnan
MCAD, MCSD.net
dkrishnan at geniant dot com
http://www.geniant.com

Nov 23 '05 #5
So, my SoapHeader object has a GetXml() implementation that is not public?

Can you point to some examples that demonstrate this?

How do I write the header to the stream in the correct place? I understand
that the SoapExtension has a priority and group associated it and that the
priority is relative. But relative to what? I am using an App.config file
to declare the soap extension. Assuming my SoapHeader already knows how to
write the correct XML for itself how do I ensure that my SoapHeader is
written inside the Envelope but before the Body?

"Dilip Krishnan" wrote:
Hello john,
You really dont have to play around with bits and bytes. Every Soap based
Object has a LoadXml and GetXml that you can use in conjunction with a XmlTextReader/Writer.
So all you need to do is write to the chained stream using an xml writer.
But u do have to chain the stream to be able to alter the stream
HTH
Regards,
Dilip Krishnan
MCAD, MCSD.net
dkrishnan at geniant dot com
http://www.geniant.com


Nov 23 '05 #6
Hello john,
Something like this...

private void AddViaElementTo Header(SoapMess age message ) //message that
comes in the process message
{
ISoapFormatter formatter = WebServicesConf iguration.Messa gingConfigurati on.AsmxPlainFor matter;
SoapEnvelope env = null;
if(message is SoapServerMessa ge)
{
try
{
if (!message.Conte ntType.StartsWi th(WebServicesC onfiguration.Me ssagingConfigur ation.AsmxPlain Formatter.Conte ntType))
//This is a hack
{
formatter = WebServicesConf iguration.Messa gingConfigurati on.AsmxAttachme ntFormatter;
}

env = formatter.Deser ialize(_origina lStream); //message from stream
}
catch(Exception )
{
HttpContext.Cur rent.Response.S tatusCode = 400;
HttpContext.Cur rent.Response.B uffer = false;
HttpContext.Cur rent.Response.O utputStream.Flu sh();
HttpContext.Cur rent.Applicatio nInstance.Compl eteRequest();
return;
}
XmlElement header = null;
header = env.CreateEleme nt("yrHeader", YourNamespaceUR I);
header .InnerText = this.ServiceUrl ;
env.Header.Appe ndChild(header) ;
}
env.Save(_repla cedStream); //Stream that you chained
if (this._replaced Stream.CanSeek)
{
this._replacedS tream.Position = 0;
}

}
HTH
Regards,
Dilip Krishnan
MCAD, MCSD.net
dkrishnan at geniant dot com
http://www.geniant.com
So, my SoapHeader object has a GetXml() implementation that is not
public?

Can you point to some examples that demonstrate this?

How do I write the header to the stream in the correct place? I
understand that the SoapExtension has a priority and group associated
it and that the priority is relative. But relative to what? I am
using an App.config file to declare the soap extension. Assuming my
SoapHeader already knows how to write the correct XML for itself how
do I ensure that my SoapHeader is written inside the Envelope but
before the Body?

"Dilip Krishnan" wrote:
Hello john,
You really dont have to play around with bits and bytes. Every Soap
based
Object has a LoadXml and GetXml that you can use in conjunction with
a XmlTextReader/Writer.
So all you need to do is write to the chained stream using an xml
writer.
But u do have to chain the stream to be able to alter the stream
HTH
Regards,
Dilip Krishnan
MCAD, MCSD.net
dkrishnan at geniant dot com
http://www.geniant.com

Nov 23 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
3715
by: ramas | last post by:
Hi, I am new to PHP scripting and i am trying to connect to a soap server (as mentioned below) using the SOAP extension comesup with PHP. Now my requirement is to add my HTTP header fields along with my SOAP request, so that the SOAP server will receive it and does some high level processing. Is it possible to add our own HTTP header fields...
5
8232
by: jb | last post by:
*Please* help --- I'm tearing my hair out. I want to use sessionstate in a webservice, accessed from a client, written in script (JScript, InfoPath). I have written my webservice (C# .NET). I have marked the method(s) with EnableSession=true. I have read everything there is to read! I am told that to reuse session, my client needs to...
3
7709
by: Sydney | last post by:
Hi, I am trying to construct a WSE 2.0 security SOAP request in VBScript on an HTML page to send off to a webservice. I think I've almost got it but I'm having an issue generating the nonce value for the UserName token. Is it possilbe at all to do this from VBScript (or jscript?)? I know I will be limited with what I can do with the SOAP...
5
4147
by: vthakur | last post by:
Hello: I have a Axis Web Service that sets the sessionid in the SOAP header for persisting the session. The client is a .Net client that processes the header as an Unknown Header. It sets the session id received from the Service request on subsequent requests to the service. However the Axis Web service does not process the SOAP header...
0
2195
by: Grzegorz Smith | last post by:
Hi All. I 'm learning ZSI to use SOAP and I desperately need help. I'm working on example from tutorial -(examples/server/send_response/ simple/wsdl/). Here are my wsdl files -http://pastebin.com/873488. I made wsdl2py wsdl2py --complexType --file=binding.wsdl and get Example_services.py and Example_Services_types.py. Here is the...
4
2470
by: Joseph Geretz | last post by:
We use a Soap Header to pass a token class (m_Token) back and forth with authenticated session information. Given the following implementation for our Logout method, I vastly prefer to simply code m_Token = null in order to destroy the session token when the user logs out. However, I'm finding that setting class instance to null results in no...
6
46772
by: John | last post by:
I'm trying to call a Webservice (Non-.NET) That requires the insertion of security credentials into the SOAP header. Up until know I've been creating Dynamic proxy classes to call web services and not been dealing with the inner workings of SOAP. Looks Like I need to learn a little about soap and Manually calling Web Services..... Any...
7
5864
by: beachdog | last post by:
I'm using Visual Studio 2005/C# to build a web client. The web server is something I've written in a different framework, which does not support generating wsdl, so I have hand-built a wsdl file, then created my proxy class by running wsdl.exe. The problem is that the SOAP message that the client generates contains an empty namespace for...
0
2228
by: vigneshrao | last post by:
Hi, I have been working on a script that loops through multiple records and sends data (one record per call) to a WS. I am supposed to make a new call for each record before sending the data. The problem I have is the first record gets processed fine where as the second record always; reason being the EAI expects it to be a seperate call...
0
7694
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8202
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7787
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
8065
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6419
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5291
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3733
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1303
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1041
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.