Reputation: 65137
How do I use HttpHandlers to create a proxy and change a SOAP request and response namespace?
Example...change this (1 line)
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Example1 xmlns="http://www.domain.com">
<DoSomething>string</DoSomething>
</Example1>
</soap:Body>
</soap:Envelope>
to this (1 line)
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Example1 xmlns="http://www.mydomain.com">
<DoSomething>string</DoSomething>
</Example1>
</soap:Body>
</soap:Envelope>
Upvotes: 0
Views: 2658
Reputation: 26
I havn't managed to get this working in a single place yet :(
IHttpHandler allows you to modify the SOAPAction in the headers, but not the body of the soap message.
SoapExtension allows you to change the body of the soap message, but not the SOAPAction in the headers.
From my testing, you need to change both for it to work...
IHTTPHandler:
public void ProcessRequest(HttpContext context)
{
string soapAction = context.Request.Headers["SOAPAction"];
context.Request.Headers.Set("SOAPAction", soapAction.Replace("OLD_NAMESPACE", "NEW_NAMESPACE"));
WebServiceHandlerFactory factory = new WebServiceHandlerFactory();
IHttpHandler handler = factory.GetHandler(context, context.Request.HttpMethod, context.Request.FilePath, context.Request.PhysicalPath);
handler.ProcessRequest(context);
context.Request.Headers.Set("SOAPAction", soapAction);
context.ApplicationInstance.CompleteRequest();
}
SOAPExtension:
public class ReWriteExtension : SoapExtension
{
Stream inputStream;
Stream outputStream;
bool bPostDeserialize = false;
public override Stream ChainStream(Stream stream)
{
if (!bPostDeserialize)
{
//We’re deserializing the message, so stream is our input
//stream
this.inputStream = stream;
this.outputStream = new MemoryStream();
bPostDeserialize = true;
return outputStream;
}
else
{
//We’re serializing the message, so stream is the
//destination of our bits
this.inputStream = new MemoryStream();
this.outputStream = stream;
return inputStream;
}
}
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)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
ReWriteOutput(message);
break;
case SoapMessageStage.BeforeDeserialize:
ReWriteInput(message);
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new Exception("invalid stage");
}
}
public void ReWriteInput(SoapMessage message)
{
inputStream.Position = 0;
var sr = new StreamReader(inputStream);
var xmlMessage = sr.ReadToEnd();
xmlMessage = xmlMessage.Replace("OLD_NAMESPACE", "NEW_NAMESPACE");
outputStream.Position = 0;
var sw = new StreamWriter(outputStream);
sw.WriteLine(xmlMessage);
sw.Flush();
outputStream.Position = 0;
}
public void ReWriteOutput(SoapMessage message)
{
inputStream.Position = 0;
var sr = new StreamReader(inputStream);
var xmlMessage = sr.ReadToEnd();
xmlMessage = xmlMessage.Replace("NEW_NAMESPACE", "OLD_NAMESPACE");
var sw = new StreamWriter(outputStream);
sw.WriteLine(xmlMessage);
sw.Flush();
}
//void Copy(Stream from, Stream to)
//{
// if (from.CanSeek) from.Position = 0;
// if (to.CanSeek) to.Position = 0;
// TextReader reader = new StreamReader(from);
// TextWriter writer = new StreamWriter(to);
// writer.WriteLine(reader.ReadToEnd());
// writer.Flush();
// if (from.CanSeek) from.Position = 0;
// if (to.CanSeek) to.Position = 0;
//}
}
Still trying desperately to get it all n one place, but I have got it working at least :/
Upvotes: 1