views:

246

answers:

2

I have to call a webservice from withing a C# programm. The webservice has most probably not a standard format. The interface description (wsdl and xsd) are very complicated, and using a proxy generating mechanismus results in hundreds of classes. The generated classes ar of little help since they are very generic, having mostly simple Object types as members.The best option is to build the SOAP message manually. That is also the way the webservice provider suggested to chose: Take the soap/xml messages that has to be sent and build the message according to the template. Now the question is how to build the message most efficiently. Of course hard coding the message string is an option, however I wonder if better options exists. If I have the complete message in a string, how do I best send the messages. Should I use a simple HttpRequest or can I use mechanisms of the wcf stack? My current approach to build the message looks like this:

string msg = envelopeBegin;
RouteType rootType = new RouteType();
XmlSerializer serializer = new XmlSerializer(typeof(RouteType));
StringWriter stringWriter = new StringWriter();
serializer.Serialize(stringWriter, rootType , customNamespace);
msg += stringWriter.ToString();
msg += envelopeEnd;

// Send the message over the wire

The Soap/xml message I have to generate looks like this

<env:Envelope>xmlns:env=http://schemas.xmlsoap.org/soap/envelope/ xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="http://www.skanska.se/oagis/9/ws/faults"&gt; 
<env:Body> 
<ska:ShowSalesOrder xmlns:ska="http://www.skanska.se/oagis/9" systemEnvironmentCode="UTV" versionID="1.0" releaseID="9.0"> 
<!--plsql=.74s--> 
<ApplicationArea xmlns="http://www.openapplications.org/oagis/9"&gt; 
<!--user_name=SEBA_RAPPE--> 
<ska:Sender> 
<LogicalID>OEBS_SE</LogicalID> 
<ComponentID>SKAIS017I</ComponentID> 
<AuthorizationID>SEBA_RAPPE</AuthorizationID> 
<ska:ResponsibilityID>XXOM_INTEGRATION_SVT</ska:ResponsibilityID> 
</ska:Sender> 
<CreationDateTime>2010-02-26T15:03:27+01:00</CreationDateTime> 
<BODID>xxxxxxxxxxxxxxxxx</BODID> 
</ApplicationArea> 
<ska:DataArea> 
<Show xmlns="http://www.openapplications.org/oagis/9"&gt; 
<ResponseCriteria> 
<ResponseExpression actionCode="Never" expressionLanguage="xPath">*</ResponseExpression> 
</ResponseCriteria> 
</Show> 
<ska:SalesOrder> 
<SalesOrderHeader xmlns="http://www.openapplications.org/oagis/9"&gt; 
<DocumentID> 
<ID>141779</ID> 
</DocumentID> 
<RequestedShipDateTime>2009-11-04T07:00:54+01:00</RequestedShipDateTime>
</SalesOrderHeader>
</ska:SalesOrder>
</ska:DataArea>
</ska:ShowSalesOrder>
</env:Body>
</env:Envelope> 
A: 

One way to do it is to create an XML skeleton template containing placeholders for the values. Read the XML and replace the values with those from your object. Post the resulting XML to the web service using HttpWebRequest.

Even that this approach might work I would strongly recommend you creating a WCF proxy class and using this instead even if the web service contains hundreds of methods and objects that are not used. As long as it is a valid WSDL, WCF will handle it. Also if there are any changes to the web service all you have to do is regenerate the proxy. To avoid the ugliness of this web service create your own infrastructure that exposes only the useful methods and classes and hides the real call.

Darin Dimitrov
+1  A: 

You can definitely still use the WCF infrastructure without requiring type definitions for all of the various messages. WCF specifically supports this through the Message class. Using it is not all that difficult. Here's some more information about them but the idea is basically you would use XML readers and writers to read and write messages.

Using the Message Class

Josh Einstein
yes, that might be true - you can use untyped Message class instances - but you cannot call a SOAP-based WCF service without going through the WCF client-side proxy stack....
marc_s
Yeah that's the idea. He could still get the benefits of the WCF client-side channels and infrastructure but without the explosion of client-side type definitions. It can be a pain when you only need 10 or so types and the WSDL defines hundreds.
Josh Einstein
@marc_s: You can use a raw TCP socket to access a WCF service if you want but they'd be a lot of plumbing to do, HttpWebRequest would be easier. What do you mean by "WCF client-side proxy stack"? It's simple to create a custom proxy derived from System.ServiceModel.ClientBase without having to resort to a verbose proxies VS.Net creates.
sipwiz
@Josh: I agree - just makes me wonder whether the original title of the question ("...without proxy...") really is the core of the question - seems a bit misleading.....
marc_s
@sipwiz: that's what I mean - you need to derive from System.ServiceModel classes. Doing so, you basically have the WCF runtime with all that's involved - behaviors, message inspectors etc. The OP was asking about calling a WS "without proxy" - that would mean directly on the wire, no WCF runtime (at least that's what I read into it).
marc_s