Untyped Web Services using ASMX

Don Box's Spoutlet

Syndication

I spent a lot of today pushing on WSDL. Along the way, I figured out how to write the "universal" method for ASMX that accepts any XML for both headers and bodies. This technique turns off the XML-object mapping but retains the SOAP header processing model + action-based dispatch.
 
Here's the signature:
 
[WebServiceBinding]
public class UniversalBinding : SoapHttpClientProtocol
{
    public SoapUnknownHeader[] Headers;
 
    [SoapHeader("UnknownHeaders", Direction = SoapHeaderDirection.InOut)]
    [SoapDocumentMethod(Action = "X:Y:Z", ParameterStyle = SoapParameterStyle.Bare)]
    [return: XmlAnyElement]
    public XmlElement[] DoIt([XmlAnyElement] XmlElement[] RequestBodies)
    {
        object[] results = this.Invoke("DoIt", new object[] { Bodies });
        return (XmlElement[])results[0];
     }
}
In order to generate the following request message:
 
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
  <S:Header>
    <T:A xmlns:T='urn:foo:bar' />
    <T:B xmlns:T='urn:foo:bar' />
    <T:C xmlns:T='urn:foo:bar' />
    <T:D xmlns:T='urn:foo:bar' />
    <T:E xmlns:T='urn:foo:bar' />
    <T:F xmlns:T='urn:foo:bar' />
    <T:G xmlns:T='urn:foo:bar' />
  </S:Header>
  <S:Body>
    <T:T xmlns:T='urn:foo:bar' />
    <T:U xmlns:T='urn:foo:bar' />
    <T:V xmlns:T='urn:foo:bar' />
    <T:W xmlns:T='urn:foo:bar' />
    <T:X xmlns:T='urn:foo:bar' />
    <T:Y xmlns:T='urn:foo:bar' />
    <T:Z xmlns:T='urn:foo:bar' />
  </S:Body>
</S:Envelope>
you would call the DoIt method like this (apologies for the raw XML api work…):
 
// create channel and connect
UniversalBinding b = new UniversalBinding();
b.Url = "http://...";
 
// Create some headers
XmlDocument doc = new XmlDocument();
doc.LoadXml(
"<Wrapper>"
+ "<T:A xmlns:T='urn:foo:bar' />"
+ "<T:B xmlns:T='urn:foo:bar' />"
+ "<T:C xmlns:T='urn:foo:bar' />"
+ "<T:D xmlns:T='urn:foo:bar' />"
+ "<T:E xmlns:T='urn:foo:bar' />"
+ "<T:F xmlns:T='urn:foo:bar' />"
+ "<T:G xmlns:T='urn:foo:bar' />"
+ "</Wrapper>"
);
 
List<SoapUnknownHeader> headers = new List<SoapUnknownHeader>();
foreach (XmlElement e in doc.DocumentElement.GetElementsByTagName("*"))
{
    SoapUnknownHeader h = new SoapUnknownHeader();
    h.Element = e;
    headers.Add(h);
}
 
// set request headers
b.Headers = headers.ToArray();
 
// create some bodies
doc.LoadXml(
"<Wrapper>"
+ "<T:T xmlns:T='urn:foo:bar' />"
+ "<T:U xmlns:T='urn:foo:bar' />"
+ "<T:V xmlns:T='urn:foo:bar' />"
+ "<T:W xmlns:T='urn:foo:bar' />"
+ "<T:X xmlns:T='urn:foo:bar' />"
+ "<T:Y xmlns:T='urn:foo:bar' />"
+ "<T:Z xmlns:T='urn:foo:bar' />"
+ "</Wrapper>"
);
 
 
List<XmlElement> bodies = new List<XmlElement>();
foreach (XmlElement e in doc.DocumentElement.GetElementsByTagName("*"))
    bodies.Add(e);
 
 
XmlElement [] ResponseBodies = b.DoIt(bodies.ToArray());
 
// b.Headers now contains the response headers, ResponseBodies now contains the response bodies
 
 
 
 

Posted Nov 18 2004, 04:16 AM by don-box

Comments

edward bakker wrote re: Untyped Web Services using ASMX
on 11-18-2004 2:02 PM
<P>don, </P>
<P>can you share a little bit of your thoughts about the following:<BR>'is a service with only a 'doit' serviceaction the way to go?' </P>
<P>personally I am not sure about this.<BR>I think XmlAnyElement and XmlAnyAttribute are very usefull when used in XSD to define messages.<BR>Using this (<A href="http://www.edwardbakker.nl/PermaLink.aspx?guid=d130a438-fe08-401c-834c-5be8dcb7fac4">example</A> from my blog) gives you very flexible messages which can handle in theory every content.<BR>These 'flexible' messages can be used in services with a generic interface, like your 'doit' example. </P>
<P>In my opinion service with these kinds of interfaces are not very easy to use. that's why i like more <BR>explicit interfaces better. As I am searching for some best practises for defining service interfaces<BR>(I wrote some <A href="http://www.edwardbakker.nl/PermaLink.aspx?guid=1040a9e6-d28d-4015-b1fa-bf19663341cf">ideas</A> on my blog) mabe you can give your opinion about generic interfaces.</P>
<P>Edward Bakker</P>
OdeToCode Link Blog wrote OdeToCode News
on 11-30-2004 8:08 AM
OdeToCode Link Blog wrote OdeToCode News
on 11-30-2004 9:31 AM
Vish wrote re: Untyped Web Services using ASMX
on 11-30-2004 10:52 AM
Hi Don,

I was trying this technique and found it to be very flexible and extensible in a way that all web services have to handle the same soap envelope and only the body gets changed across the transfer. Can you briefly chalk out the advantages you think over a traditional proxy generated webservices. Reply me at kakkarv@hsn.net.
Thanks for your help !

Vish

Add a Comment

(required)  
(optional)
(required)  
Remember Me?