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.
Related
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.
Using WCF Restful service with XmlSerializer I get the below response.
<?xml version="1.0" encoding="utf-8"?>
<availabilityResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xyz.com/ABCService">
<availabilityResult>
<title xsi:type="Availability_1">
<titleId>0010327457</titleId>
<availability>
<purchasable>false</purchasable>
<availableCopies>0</availableCopies>
<totalCopies>0</totalCopies>
</availability>
</title>
</availabilityResult>
</availabilityResponse>
(I wish to remove xmlns:xsd, xmlns:xsi and xsi:type tags)
"Availability_1" is one my derived type i used in my code. I really do not want to show this in the response.
I am using XmlSerialzer by specifying [XmlSerializerFormat] at the service contract.
WCF is able to serialize my response properly but the only issue i have is with the extra xmlns tags. Yes, I know they are useful stuff there. But, the client is interested only in the plain xml.
By looking at various posts in stackoverflow i understood i could do this by overriding few of the methods of XmlTextWriter. But the problem I have is how to let the WCF know to use my customXmlWriter (inherited from XmlTextWriter) instead of generic XmlTextWriter while serialization.
How to pass my customXmlTextWriter to the XmlSerializer which i do not have any control at this point.
I just created my data classes and defined the service contract methods from my end but did not have to do any of the serialization stuff from my side as the WCF takes care of it on its own.
A slightly different idea, but it's in the line of separation of concerns, as writing custom serialisers to actually make the responses sort of "invalid" seen from a true compliancy principe can be seen as an anti-pattern.
My idea is to develop your own IIS custom HTTP handlers and add it to the IIS processing pipeline. Doing so, will allow you to expose both the tweaked responses and the fully compliant ones.
The custom HTTP handler could use a simple XSLT to remove the required namespaces.
Have a look at this article to get started - http://www.iis.net/learn/develop/runtime-extensibility/developing-iis-modules-and-handlers-with-the-net-framework
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").
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.
I need to intercept the response of a service created using WCF with webHttpBinding (REST based service).
Now I want the XML emitted in a customized way. For e.g, currently a service method returns output like this:
<User xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<UserCellInfo>+91-98102239</UserCellInfo>
<UserDepartment>.NET Projects</UserDepartment>
<UserID>A10129</UserID>
<UserName>Jeff Thomson</UserName>
</User>
but I want it in a different custom way.Something like below
<?xml version="1.0" encoding="UTF-8"?>
<rsp>
<User>
<UserCellInfo>+91-98102239</UserCellInfo>
<UserDepartment>.NET Projects</UserDepartment>
<UserId>A10129</UserId>
<UserName>Jeff Thomson</UserName>
</User>
</rsp>
In MSDN, I read that I need to use IDispatchMessageInspector to intercept the XML that goes out. But I couldn't find any code reference or example for it.
Any good ideas how to achieve this?
So I assume your WCF service method returns an instance of a User object in this method call, right?
Why not just define a wrapper class called rsp that contains the User instance? Then returning the rsp object would render in the desired style. Just a nice clean wrapper - no messy XML manipulation on the fly......