Set namespaces in SOAP envelope for classes generated using svcutil - wcf

We are working on a third party integration using WSDLs and XSDs that were provided to us. We've used svcutil to generate all the proxy classes for us which works fine. When we test with SoapUi everything works fine, however, when we try to send the response to our partner they're rejecting the SOAP message because the namespaces are being defined in the message header and body rather than the SOAP envelope.
Unfortunately, I can't make our partner change their process to accept our messages (even though I believe they are technically correct since we are defining the namespaces before we use them in the XML, just not where they expect them). I know I could put a message inspector in to massage the SOAP message before goes out, but I'd rather not go to that level of processing.
Are there any settings either for svcutil or even on the serialization attributes that we could set to have WCF output the namespaces on the envelope instead?
What they want:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:h="http://theirdomain.org/service">
<s:Header>
<h:myType>
<version>V1.0</version>
</h:myType>
</s:Header>
<s:Body>
<h:someElement />
</s:Body>
</s:Envelope>
What we're sending:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" >
<s:Header>
<h:myType xmlns:h="http://theirdomain.org/service">
<version>V1.0</version>
</h:myType>
</s:Header>
<s:Body>
<h:someElement xmlns:h="http://theirdomain.org/service"/>
</s:Body>
</s:Envelope>

I think the right extensibility point for this may be a custom encoder (see http://msdn.microsoft.com/en-us/library/ms735115.aspx , or the samples at http://msdn.microsoft.com/en-us/library/ee960159.aspx , especially the first one). In the custom encoder, you would write the SOAP Envelope yourself (with the correct namespaces), and then call methods on the Message object to write out the headers and body (e.g. WriteBodyContents, see http://msdn.microsoft.com/en-us/library/ms734675.aspx - under "Writing Messages").

Related

How can I change xmlns of root tag Envelop in soap request in WCF

I need to change xmlns of root tag Envelope in soap request in WCF. Like now WCF creating following request
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"></s:Envelope>
But I need to create like following
<soapenv:Envelope xmlns:abc="abc.astute.ca/"; xmlns:xyz="xyz.astute.ca/"; xmlns:asd="asd.astute.ca/"; xmlns:qwe="qwe.astute.ca/"; xmlns:soapenv="schemas.xmlsoap.org/soap/envelope/">
Any idea?
I would advise not to do it (there is almost never a reason to do it). If this is a requirement than you could do it in a custom message encoder - you would need to change all places where the prefix is referred to as well.

Why is a message in WCF seemingly always in SOAP format?

I have implemented a message inspector in WCF by implementing IDispatchMessageInspector.
Putting a break point on this method...
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
// Impementation
}
... I can look at the request object to see what is inside.
Clearly I dont understand WCF enough because whatever endpoint binding I use (basichttp, nettcp and netpipe) the message inside is always represented in SOAP format e.g.
<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">
<s:Header>
-- headers --
</s:Header>
<s:Body>
-- body --
</s:Body>
</s:Envelope>
Is this because doing a .ToString() on the request object just represents the message in SOAP format?
I imagined that using another protocol e.g. netTcp would result in a different message payload.
Also lets say I wanted to represent my data in JSON format how would I go about doing this? Or would I end up with JSON formatted data structures inside a SOAP envelope?
It is because all bindings you mentioned are designed to use SOAP protocol. They are using either TextMessageEncoder or BinaryMessageEncoder and both these work with SOAP envelopes (except the situation where you use TextMessageEncoder in custom binding with MessageVersion set to None).
The only out-of-the box binding allowing other message formats is WebHttpBinding which uses WebMessageEncoder supporting both XML and JSON.

VB.net SOAP webservice client "Unmarshalling Error: unexpected element ..."

I am building a client in VB.net for calling webservices methods from a partner organisation.
I am following the guidelines at http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soaphttpclientprotocol%28v=VS.71%29.aspx because I can't get it to work using the Web References feature of Visual Studio 2010 (when I try to do that it turns the methods from the WSDL into classes).
I have created a proxy class and can instantiate an object of that class no problem.
However, when I try to call a method which requires arguments I get this error:
Unmarshalling Error: unexpected element (uri:"http://api.service.apimember.emailvision.com/", local:"key"). Expected elements are <{}key>,<{}login>,<{}pwd>
Does anyone have any idea why this might be? (If it's helpful I can post my code and the location of the WSDL.)
(P.S. I can get the whole thing to work fine in PHP using ZF Soap classes, but for various reasons I need to get it to work using .Net)
Edit to add: I have used Wireshark to examine the outgoing and incoming SOAP message to compare them with the messages being sent via SoapUI, where it all works fine.
What this has shown is that my VB client is sending a message where the namespace of the web service I am trying to access is declared as an attribute of the method, and not in the soap:envelope attributes.
Here is an example:
WORKS (produced by SoapUI):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:api="http://api.service.apimember.emailvision.com/">
<soapenv:Header/>
<soapenv:Body>
<api:openApiConnection>
DOESN'T WORK (produced by my VB.net code):
<?xml version="1.0" encoding="utf-8"?>
<soap:envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:body>
<openApiConnection xmlns="http://api.service.apimember.emailvision.com/">
I think I need to declare the xmlns 'api' in the envelope element, so I need to figure out how to do this in my VB.net code.
OK, turns out I was using System.Web.Services.Protocols.SoapDocumentMethodAttribute but I should have been using System.Web.Services.Protocols.SoapRpcMethodAttribute.
Using the RPC binding style produces the message body format the remote service requires. Having read up a bit about how the attributes in the MS code I was basing my code on were affecting my output I came across this page http://msdn.microsoft.com/en-us/library/k1y9z356(v=vs.80).aspx which led me to changing the binding method, and that works.

Change namespace Prefix WCF Envelope

I was wondering is there anyway to change the namespace prefix for the WCF SOAP request?
As you can see in the example below, The Envelope has namespace "http://www.w3.org/2005/08/addressing" with prefix 'a'. I want to change this to 'foo'. How can I do that.
Note I dont have control over service code I can only create proxy class from the WSDL .
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.starstandards.org/webservices/2005/10/transport/operations/MyAction</a:Action>
<h:payloadManifest xmlns="http://www.starstandards.org/webservices/2005/10/transport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:h="http://www.starstandards.org/webservices/2005/10/transport">
<manifest contentID="Content0" namespaceURI="http://www.starstandard.org/STAR/5" element="TESTMETHOD" version="5.2.4"></manifest>
</h:payloadManifest>
<h:Identity xmlns="urn:xxx/xxx/" xmlns:h="urn:xxx/xxx">
<SiteCode>XXXXXX</SiteCode>
</h:Identity>
<a:To>urn:xxx/xxx/Method1</a:To>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">XXXXX</MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
</s:Header>
This can be done on Client or Server side by using a MessageFormatter. You can also change this with a MessageEncoder, but this has many problems.
This article describes how to do this on server side using a MessageFormatter and also the downside of a MessageEncoder:
http://vanacosmin.ro/Articles/Read/WCFEnvelopeNamespacePrefix
What you need to do is to apply the MessageFormatter client side (maybe using ApplyClientBehavior instead of ApplyDispatchBehavior). Also, in the custom message class you need to add your namespace as attribute, with the "foo" prefix (in the OnWriteStartEnvelope method).
Unfortunately, there is no easy way (like applying some attributes) that will make the change you need.
WCF provides ability to control most of the SOAP Envelop details using message contracts. But I doubt if you can do something with the namespace prefix. You can control the namespace however.
Please refer to Using Message Contracts
I'm not aware of any way to control the prefixes WCF uses in its standard message encoders.
I think you would have to write a custom message encoder if you want the message on the wire to use different prefixes.

WCF service custom response

I have developed a demo WCF service with basicHttpBinding and I'm getting WCF response as fellow -
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<TestResponse xmlns="http://tempuri.org/">
<TestResult>hi Test</TestResult>
</TestResponse>
</s:Body>
</s:Envelope>
But I need WCF response in following format-
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
-->><t:TestResponse xmlns:t="http://tempuri.org/">
<TestResult>hi Test</TestResult>
</TestResponse>
</s:Body>
</s:Envelope>
so what can I do to get this reponse??
Notice that the two responses you have aren't equivalent: in the first one the <TestResult> element is in the tempuri.org/ namespace, while in the second one it's on the default ("") one (you'd need to prefix TestResult with "t:" as well to maintain the same XML semantics. To accomplish this, there's nothing in WCF which will do it out of the box, but you can change it yourself using one of the many extensibility points of the platform. Take a look at http://blogs.msdn.com/b/carlosfigueira/archive/2010/06/13/changing-prefixes-in-xml-responses.aspx which deals exactly with that.