Webservice response with nullable doubles is not deserialized properly - c#

I'm calling a webservice from one of our partners. I have no problem calling it and I get a result.
The response has nullable doubles. In fiddler I see in the XML of the response these doubles have values, but somehow these fields do not get deserialized to my proxy class because these fields have the value null there.
This is a summary of the response xml I get, somehow the value in id27 does not get serialized, but the boolean in id26 does. Why?
<extras soapenc:arrayType="ns2:Extra[16]" xsi:type="soapenc:Array">
<extras href="#id1"/>
<extras href="#id2"/>
...
</extras>
...
<multiRef id="id1" soapenc:root="0"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns6:Extra" xmlns:ns6="http://model.bookingservice.app.traserv.com"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<assignments xsi:type="ns6:Assignment" xsi:nil="true"/>
<category xsi:type="xsd:string">def_Surety</category>
...
<orderUnit xsi:type="xsd:string">Verblijf</orderUnit>
<payAtLocation href="#id26"/>
<price href="#id27"/>
<priceNotes xsi:type="xsd:string" xsi:nil="true"/>
...
</multiRef>
...
<multiRef id="id26" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="xsd:boolean" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">true</multiRef>
<multiRef id="id27" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:double" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">345.0</multiRef>

I found WCF clients and axis webservice do have these problems.
You can solve it in the proxy, which is obviously not nice because you have to edit generated classes. Or you can change the webservice, which is also a problem because you have not always control over that one.
Anyway I found these items about it:
http://www.tomergabel.com/GettingWCFAndApacheAxisToBeFriendly.aspx
Why won't .NET deserialize my primitive array from a web service?

Related

Converting SOAP XMLString to C# object

[Question Modified] I am completely new to XML and am calling a web service(WCF). The request is expected to be in the below format:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:CreateLead>
<!--Optional:-->
<tem:xDoc>
<lead>
<![CDATA[<CreateLead>
<FIRSTNAME>John</FIRSTNAME>
<LASTNAME>Doe</LASTNAME>
<MOBILE>9999999999</MOBILE>
<EMAIL>john#doe.com</EMAIL>
<SOURCE>Website</SOURCE>
<SUBSOURCE>Blog</SUBSOURCE>
<WEBREMARKS></WEBREMARKS>
<TIMETOCALL>26/02/2018 18:40:15 PM</TIMETOCALL>
<FAILEDSTEP>Step 1</FAILEDSTEP>
<FOILIONO>123</FOILIONO>
<SCHEMECODE>123</SCHEMECODE>
<AMOUNT>100</AMOUNT>
<REGEVENT></REGEVENT>
<FEEDBACK></FEEDBACK>
</CreateLead>
]]>
</lead>
</tem:xDoc>
</tem:CreateLead>
</soapenv:Body>
</soapenv:Envelope>
I have created the proxy class and the below is the signature of the method to be called:
public System.Xml.XmlElement CreateLead(System.Xml.XmlElement xDoc)
{
return base.Channel.CreateLead(xDoc);
}
I am passing the complete SOAP as a string literal and converting it into an XMLElement and am getting a proper response. I wish to pass it as a C# object. Is there a way to create a class according to my above SOAP request?
I tried copying the XML and using Visual Studio's paste special to Paste XML as class but it is somehow not creating an exact replica of the above mentioned SOAP XML.
I need it to be completely similar to the above SOAP format.
Please help.

C# returning null on certain SOAP requests

We have been battling with a SOAP related problem for some time. We have a SOAP based API that can be called from a number of languages (PHP, Ruby etc). C#, however, seems to choke in certain circumstances.
Unfortunately, it is not clear to us why it dies. We are not C# people, but we did get an external, C# person to look at the problem. And, they were also baffled!
The wdsl can be seen here: http://sandbox.knowledgetree.com/ktwebservice/webservice.php?wsdl (yes, its large).
From C#, session creation, and several other calls work happily. However, the get_folder_contents call fails. The call executes, and fiddler shows valid XML being returned. However, C#'s return value is null.
The request, per Fiddler, is as follows:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<s:get_folder_contents>
<session_id xsi:type="xsd:string">or8llmjj5rm7co9h5p2k762s77</session_id>
<folder_id xsi:type="xsd:int">99</folder_id>
<depth xsi:type="xsd:int">1</depth>
<what xsi:type="xsd:string">DFS</what>
</s:get_folder_contents>
</s:Body>
</s:Envelope>
(I've added spaces and line breaks to the fiddler logs).
The response, per Fiddler (but, again, formatted for clairty), is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-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:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns4="urn:KnowledgeTree" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<SOAP-ENV:get_folder_contentsResponse>
<item xsi:type="ns4:kt_folder_contents">
<status_code xsi:type="xsd:int">0</status_code>
<message xsi:type="xsd:string"></message>
<folder_id xsi:type="xsd:int">99</folder_id>
<folder_name xsi:type="xsd:string">Nic</folder_name>
<full_path xsi:type="xsd:string">Nic</full_path>
<items xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="ns4:kt_folder_item[0]" xsi:nil="true"/>
</item>
</SOAP-ENV:get_folder_contentsResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The (crude) C# application we used to test is as follows:
public partial class Form1 : Form
{
private string _sessionId;
private KnowledgeTreePortClient _webService;
public Form1()
{
InitializeComponent();
_webService = new KnowledgeTreePortClient();
_webService.loginCompleted += new EventHandler<loginCompletedEventArgs>(WebLoginCompleted);
_webService.loginAsync("username", "secret_password", "nil", "c-sharp-test");
}
private void WebLoginCompleted(object sender, loginCompletedEventArgs e)
{
_sessionId = e.Result.message;
_webService.get_folder_contentsCompleted += GetFolderComplete;
_webService.get_folder_contentsAsync(_sessionId, 99,1, "DFS");
}
private void GetFolderComplete(object sender, get_folder_contentsCompletedEventArgs e)
{
}
}
I'd prefer to fix this from the client (C#) side. But, any guidance as to what we are doing wrong would be much appreciated!
renen.
I tried it and got the same response.
The way I resolved it and got the response you're looking for is by adding a web reference instead. To do this right click on the references folder of your project, select add service service reference, click on the web reference button on the bottom and then proceed from there.
The proxy classes generated by that method behave as you'd expect.
As to why the service reference is not working I'm still looking into that....
EDIT:
So I've check the response Xml against the WSDL and I cannot spot any namespace mismatches. I found a couple of articles detailing how to resolve sub elements (like arrays) being null which was mostly because of a namespace mismatch - but in your case the whole kt_folder_contents value is bull and as far as I can see the namespace (urn:KnowledgeTree) in the generated wrappers is correct.
I hope someone else can give a fix for this - else if the Web Reference generated proxy works for you...
Not sure whether this makes a difference in view of the comments regarding true root cause but I have found that C#/VS interprets the entire return value as null when there is an array within the SOAP response that contains a xsi:nil="true"/> value as in:
items xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="ns4:kt_folder_item[0]" xsi:nil="true"/>
I am trying to consume the webservice in a WINFORMS application and responses without this array value seem to work fine but the two that show null return values in their response object both have the nil="true" for an array that is part of the object. Don't know if it's merely coincidence but appears to be related to comment on profile (WS-I BP1) compliance?
Alan
I came across this problem and the Web Reference proxy workaround that #QuintonBernhardt suggested worked for me. Just want to mention how to add Web Reference in recent Visual Studio versions (2017+):
In regular add service reference dialog, choose "Advanced"
Then in the compatibility section select "Add Web Reference"

How to retrieve a collection out of an SOAP message

I'm using a webservice for render company information based on a special company number.
But i can not get data out of the response SOAP message.
You can see an example of the response soap message. (I left out some company information the tags).
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<businessGetDossierV3Response xmlns="http://www.webservices.nl/soap/">
<out>
<paging>
<curpage>1</curpage>
<perpage>10</perpage>
<numpages>1</numpages>
<numresults>1</numresults>
<maxresults>100</maxresults>
</paging>
<results>
<item>
<DossierNo></DossierNo>
<SubDossierNo></SubDossierNo>
<ChamberNo></ChamberNo>
<Legalformcode></Legalformcode>
<LegalformcodeText></LegalformcodeText>
<Tradename45></Tradename45>
<EstablishmentPostcode></EstablishmentPostcode>
<EstablishmentCity></EstablishmentCity>
<EstablishmentStreetname></EstablishmentStreetname>
<EstablishmentHouseNo></EstablishmentHouseNo>
<CorrespondencePostcode></CorrespondencePostcode>
<CorrespondenceCity></CorrespondenceCity>
<CorrespondenceStreetname></CorrespondenceStreetname>
<CorrespondenceHouseNo></CorrespondenceHouseNo>
</item>
</results>
</out>
</businessGetDossierV3Response>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
! this is the result i see on the demo client !
But this is my code in C#
nl.webservices.ws1.BusinessDossierV3PagedResult result = null;
result = myserviceBusiness.businessGetDossierV3(KVKnr, "0000", 1);
I want to do something like this (but with the results instead of paging part)
int page = result.paging.numpages;
Then I should be like this I suppose
string city = result.results.item.CorrespondenceCity;
But this is giving a fault message
So in Visual studio 2010, i can only retrieve the data in the paging part of the xml and put it into a textbox, but not from results part. Is this because the result part is some kind of Collection?
So yes, how can i put the data from the tags EstablishmentPostcode and EstablishmentCity in a textbox on my default page?
thanks in advance
You could try adding your SOAP service as a web reference to the project. http://msdn.microsoft.com/en-us/library/tydxdyw9.aspx
If you don't want to do this and would rather work on the XML directly you could use xpath to get access to all the item elements in your results element.
http://www.stardeveloper.com/articles/display.html?article=2009031001&page=1
One thing to be careful of when using xpath is that you use the correct xml namespace for the node you're trying to select.
Ben

WCF consuming multiple possible REST responses

I've recently started reading about the WebHttpBinding usage in WCF and being able to consume REST services, however, I've been stumped on this one for a bit now.
I'm writing a service that makes a single request to a given api, however, can return one of many responses.
For example, the generic response:
<ActualResponse>
<ResponseItem>
<Name />
<Area />
</ResponseItem>
</ActualResponse>
However, if something were invalid in the outgoing request or the responding service itself was experiencing any sort of issue a returning response would be:
<ErrorResponse>
<Message />
</ErrorResponse>
Pedram Rezaei had a great post on consuming REST services, which is where I borrow most of my information from. From what I can tell, we can create an object as long as the object has serializable attributes defined. The issue being, there's no condition to which class to be created(ErrorResponse/ActualResponse).
I'm unsure if I should be looking at some sort of TryParse functionality that sends the initial request and catches the error if no deserialization can occur or if there is a more elegant approach.
I'm fairly new to the WCF world, so the possibility exists I may be entirely overlooking something!
I think you can borrow some practice from SOAP, which has a hierarchy like so:
<soap:Envelope>
<soap:Body>
... message contents
</soap:Body>
</soap:Envelope>
I'm not suggesting that you use SOAP, I'm suggesting that you learn from the design employed by SOAP. What SOAP does is embed the successful (or in your words "actual") response within the Body, or return a soap:Fault within the Body.
a success in SOAP might look like this:
<soap:Envelope>
<soap:Body>
<ActualResponse>... </ActualResponse>
</soap:Body>
</soap:Envelope>
while a fault might look like this:
<soap:Envelope>
<soap:Body>
<soap:Fault>... </soap:Fault>
</soap:Body>
</soap:Envelope>
In your case, you might have this:
<ServiceResponse>
<ActualResponse> ... </ActualResponse>
</ServiceResponse>
or
<ServiceResponse>
<Fault> ... </Fault>
</ServiceResponse>
And XML Serialization is really good at that. . .
But it sounds like you have no control over the envelope. The fact is that you can get multiple different responses. To handle this, you could wrap the actual response received in a contrived XML envelope, and deserialize the result of that.
If you get <ActualResponse>...</ActualResponse> , wrap it in a deserializable envelope to get something like <ServiceResponse><ActualResponse>...</ActualResponse></ServiceResponse>, then deserialize.

Consuming in Java a .NET Web Service that requires a custom SOAP Header

So I need to consume a Web Service that uses a custom SoapHeader, as described below. What is the simplest way to pass the correct values through this header using Java. I'm using Netbeans.
<?xml version="1.0" encoding="utf-8"?\>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<CustomSoapHeader xmlns="http://snip">
<UserName>"string"</UserName>
<Password>"string"</Password>
</CustomSoapHeader>
</soap:Header>
<soap:Body>
<SomeWebMethod xmlns="http://snip" />
</soap:Body>
</soap:Envelope>
EDIT: What's the best way to display XML on Stack Overflow?
It might help to add that the Web Service is implemented in .NET and I cannot change the server side code.
Here are the basic steps, assuming you're doing this on the client side:
Install a HandlerResolver on your service interface (service.setHandlerResolver())
Override HandlerResolver.getHandlerChain() to insert your own implementation of SOAPHandler
Implement SOAPHandler.handleMessage() to modify the SOAP header before it's sent out
You can pass parameters to your handler through the request context:
Map<String, Object> context = ((BindingProvider) port).getRequestContext();
context.put("userName', "foo");
...
in handleMessage() you can get at the header like this:
public boolean handleMessage(SOAPMessageContext context) {
...
SOAPMessage msg = context.getMessage();
msg.getSoapHeader();
...
}
Hope that helps. I'm guessing there's also a way to do this stuff with annotations as well.

Categories