Receive and return bare XML in C#/ASP.NET Web Service

R

Richard A. Wells

All I wanted to do was implement a web service where I'd receive an
XML document and return one in response. I'd already figured out how
to use XmlReader and XmlWriter classes to do the XML work I need to
do. And all that fancy ASP.NET serialization really got in my way.

Reading articles by Yasser Shohoud, Tim Ewald, and Matt Powell led me
down many promising paths, along the way writing an XSD schema file
for my messages, trying to generate a interface using wsdl.exe, and
even considered implementing a SOAP extension to get at the streams.
But once I read Powell's article on "The Power of XmlElement
Parameters in ASP.NET Web Methods" I realized I should be able to do
what I needed, once I sussed out the use of C# attributes.

Since it took me days to figure all this out I thought I should post
the (complete, compilable, code-behind) source for a simple 'echo' web
service that demonstrates this, to help those trying to do similar
things.

The only thing that this shows that wasn't in Powell's article is the
use of the [return: XmlAnyElement] attribute declaration on the web
method. This (at least in combination with the
SoapParameterStyle.Bare) causes the XML returned to be an immediate
child of the <soap:Body> element. Otherwise one gets an interposed
<echoResult> which, at least in my case, is undesirable.

Note that this results in very unrestrained WSDL for your operation.
From echo.asmx?wsdl:

<message name="echoSoapIn">
<part name="input" type="s0:any"/>
</message>
<message name="echoSoapOut">
<part name="echoResult" type="s0:any"/>
</message>

In my case, I'm going to use this as the basis for an intranet web
service, so I don't mind. And I do plan to parse the XML I receive
with XmlValidatingTextReader. But I *believe* using the
WebServiceBindingAttribute with a hand-crafted WSDL file one could
cause ASP.NET to do the validation while having the method still
receive the bare XML. But maybe not.....?

Cheers,
Richard

---- begin echo.asmx.cs ----

using System;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml;
using System.Xml.Serialization;

namespace echo
{
[ WebService(
Description="echo web service - receives bare SOAP body and echoes
it back as SOAP body, without wrapping or encoding",
Namespace="http://localhost/echo") ]
public class echows : System.Web.Services.WebService
{
public echows() { }

[WebMethod]
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
[return: XmlAnyElement]
public XmlDocument echo([XmlAnyElement]XmlElement input)
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(input.OuterXml.ToString());
return xml;
}
}
}


---- end echo.asmx.cs ----
 
J

JD

Richard,

Have you been able to support Http POST without SOAP with XML documents?
Your sample only supports SOAP.

Thanks for posting,
James

Richard A. Wells said:
All I wanted to do was implement a web service where I'd receive an
XML document and return one in response. I'd already figured out how
to use XmlReader and XmlWriter classes to do the XML work I need to
do. And all that fancy ASP.NET serialization really got in my way.

Reading articles by Yasser Shohoud, Tim Ewald, and Matt Powell led me
down many promising paths, along the way writing an XSD schema file
for my messages, trying to generate a interface using wsdl.exe, and
even considered implementing a SOAP extension to get at the streams.
But once I read Powell's article on "The Power of XmlElement
Parameters in ASP.NET Web Methods" I realized I should be able to do
what I needed, once I sussed out the use of C# attributes.

Since it took me days to figure all this out I thought I should post
the (complete, compilable, code-behind) source for a simple 'echo' web
service that demonstrates this, to help those trying to do similar
things.

The only thing that this shows that wasn't in Powell's article is the
use of the [return: XmlAnyElement] attribute declaration on the web
method. This (at least in combination with the
SoapParameterStyle.Bare) causes the XML returned to be an immediate
child of the <soap:Body> element. Otherwise one gets an interposed
<echoResult> which, at least in my case, is undesirable.

Note that this results in very unrestrained WSDL for your operation.
From echo.asmx?wsdl:

<message name="echoSoapIn">
<part name="input" type="s0:any"/>
</message>
<message name="echoSoapOut">
<part name="echoResult" type="s0:any"/>
</message>

In my case, I'm going to use this as the basis for an intranet web
service, so I don't mind. And I do plan to parse the XML I receive
with XmlValidatingTextReader. But I *believe* using the
WebServiceBindingAttribute with a hand-crafted WSDL file one could
cause ASP.NET to do the validation while having the method still
receive the bare XML. But maybe not.....?

Cheers,
Richard

---- begin echo.asmx.cs ----

using System;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml;
using System.Xml.Serialization;

namespace echo
{
[ WebService(
Description="echo web service - receives bare SOAP body and echoes
it back as SOAP body, without wrapping or encoding",
Namespace="http://localhost/echo") ]
public class echows : System.Web.Services.WebService
{
public echows() { }

[WebMethod]
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare)]
[return: XmlAnyElement]
public XmlDocument echo([XmlAnyElement]XmlElement input)
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(input.OuterXml.ToString());
return xml;
}
}
}


---- end echo.asmx.cs ----
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top