Microsoft left something out when designing web services, fortunately there is a nifty way to obtain the original SOAP request within a C# web service.
I’ve written an article on this topic before. Its possible to obtain the SOAP request body for logging purposes by using SoapExtensions. And that’s all well and good if you want to log the traffic between your SOAP web service and the outside world. But what if you want to change the behaviour of your web services based on the input that comes in?
Say for example, you want to validate your SOAP request against an XML schema to enforce additional validation than what comes out of the box with .NET by default.
The process is quite simple, you need to find the Request object and load the contents of little known property called ‘InputStream‘. You can mine the contents of the SOAP request and load them into an XML document easily as follows:
Using this technique we can create a simple Web Service that performs a simple ‘Echo’ of whatever you send into it. See the following code:
using System;
using System.Collections.Generic;
using System.Web;
using System.Xml;
using System.IO;
using System.Text;
using System.Web.Services;
using System.Web.Services.Protocols;
namespace SoapRequestEcho
{
[WebService(
Namespace = "http://soap.request.echo.com/",
Name = "SoapRequestEcho")]
public class EchoWebService : WebService
{
[WebMethod(Description = "Echo Soap Request")]
public XmlDocument EchoSoapRequest(int input)
{
// Initialize soap request XML
XmlDocument xmlSoapRequest = new XmlDocument();
// Get raw request body
using (Stream receiveStream = HttpContext.Current.Request.InputStream)
{
// Move to begining of input stream and read
receiveStream.Position = 0;
using (StreamReader readStream =
new StreamReader(receiveStream, Encoding.UTF8))
{
// Load into XML document
xmlSoapRequest.Load(readStream);
}
}
// Return
return xmlSoapRequest;
}
}
}
We can quickly test our SOAP request and check that we are processing whatever XML is being sent in and its coming out the other side untouched.
Next Steps: Performing Schema Validation
Now you can do what you want with your xmlSoapRequest object. It’ll contain exactly the same request as was sent into SOAP in the first place.
If you are after schema validation.The next step is to populate the xmlSoapRequest
.Schemas
property and then fire off the xmlSoapRequest
.Validate()
method.
Piece of cake.
E-commerce website featuring relaxation and skincare products by UK Spa design and management company. The project involved client checkout and ordering process embedded in existing Content Management solution.
C# Web Services provide an easy interface to incoming SOAP data because the SOAP message has already been deserialised at the entry point of a WebMethod.
The downside is that sometimes you’ll need to have access to the full SOAP request: body, headers and everything for tasks such as diagnosing any errors (which message broke the web service) or providing graceful handling of third party web services.
At first you’d think that the Request object can provide this information with methods such as Request.BinaryRead() but unfortunately when you’re using SOAP all you get there is a querystring.
The solution here is to use the SOAP Extensions. Here is some sample code:
public class SoapMessageLogger : SoapExtension
{
//…
public override void ProcessMessage(SoapMessage message)
{
switch(message.Stage)
{
case SoapMessageStage.BeforeDeserialize:
LogResponse(message); break;
case SoapMessageStage.AfterSerialize:
LogResponse(message); break;
// Do nothing on other states
case SoapMessageStage.AfterDeserialize;
case SoapMessageStage.BeforeSerialize;
default: break;
}
}
//…
}
A central point of contact for all Nandos’ stores. From the central login page each user has a set of applications which they can launch automatically by just clicking on the icon.