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