How to retrieve a collection out of an SOAP message - c#

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

Related

How Do I Change XML Prefix For WCF Client Request c#?

Due to requirements from a web service that I have no control over, I need to change my ns prefixes from the defaults of "s" and "h". The service provider has provided a .wsdl file for my service reference, however, they do not appear to have an online wsdl for metadata exchange. I have emailed them and they confirmed that the prefixes have to be specific values (right or wrong on their part, I have to make this work).
Can someone please tell me the easiest way to change these values? Is there something I can modify in Reference.cs? Do I have to implement some sort of message formatting logic into my requests to change the values just prior to sending out the request?
Every element in the XML has to have a prefix of a specific value (2 values total), or the WS will not accept the request and simply returns HTML in the response. When I copy the request captured in Fiddler, over to SOAP UI and update the prefixes to what they require, the request works fine when executed from Soap UI. I'm simply not finding any simple solutions to this seemingly simple problem for c# VS 2017 development platform.
Also worth noting, when I load the .wsdl file into Soap UI, Soap UI generates all of the ws operations and requests with the correct, desired prefixes that I need in my c# app. How does Soap UI know the exact prefixes to generate in the requests?
I need to modify this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:FooListHeader xmlns:h="http://foo.foo.com/Hello" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<h:FooList>
<h:FooStatement>
<h:Title>Foo</h:Title>
<h:Value>123</h:Value>
</h:FooStatement>
</h:FooList>
</h:FooListHeader>
</s:Header>
<s:Body>
<GetFooRequestType xmlns="http://foo.foo.com/Hello">
<MessageRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ConFooRequest/>
</MessageRequest>
</GetFooRequestType>
</s:Body>
</s:Envelope>
To something like this:
<soapenv:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:foo="http://foo.foo.com/Hello">
<soapenv:Header>
<foo:FooListHeader xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<foo:FooList>
<foo:FooStatement>
<foo:Title>Foo</foo:Title>
<foo:Value>123</foo:Value>
</foo:FooStatement>
</foo:FooList>
</foo:FooListHeader>
</soapenv:Header>
<soapenv:Body>
<foo:GetFooRequestType xmlns="http://foo.foo.com/Hello">
<foo:MessageRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<foo:ConFooRequest/>
</foo:MessageRequest>
</foo:GetFooRequestType>
</soapenv:Body>
</soapenv:Envelope>
Example c# code:
public GetYaddaYaddaResponseType CheckConnection()
{
Yadda client = new Yadda();
var msgRequest = new GetYaddaYaddaResponseType { ConnectionConfirmationRequest = new ConfirmConnectRequestType() };
List<Statement> statementList = new List<Statement>
{
new Statement { Name = "Yo", Value = "123" },
new Statement { Name = "Hey", Value = "123" },
};
var header = new StatementHeader
{
StatementList = statementList.ToArray()
};
var response = client.GetYaddaYaddaMessage(ref header, msgRequest);
return response;
}

How to read soap response in c#?

Soap Respose as:
<?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>
<LoginResponse xmlns="http://example.com/SystemIntegration">
<FirstName>#FirstName</FirstName>
<LastName>#LastName</LastName>
</LoginResponse>
</soap:Body>
</soap:Envelope>
I'm trying to read it as:
XDocument doc = XDocument.Parse(strReturnStatus);
List<XElement> result = doc.Elements("LoginResponse").ToList();
for (int intc = 0; intc <= result.Count - 1; intc++)
{
strResponseCode = result[intc].Element("FirstName").Value.ToString();
strResponseText = result[intc].Element("LastName").Value.ToString();
}
But it returning null result.
How to read above respose in asp.net c#??
The easiest thing is to create a proxy class for your service.
You can do that using the 'Add Service Reference' option in Visual Studio. Enter the URL of the service, and Visual Studio will generate the source code for you.
From that point you can access the service using C# code. No need to manually extract the payload of the SOAP message.
Note if you are the implementator of the service: ASMX webservices are deprecated for a long time already. If you can, use WCF.
Use Descendants() method in XDocumentobject to navigate through XML nodes to get elements, you can follow steps provided in this post Using C# to parse a SOAP Response

RestSharp to edit one element of xml file

For the documentation of the API I am using, the instructions are:
To edit an existing resource: GET the full XML file for the resource you want to change (/api/customers/7), edit its content as needed, then PUT the whole XML file back to the same URL again.
Now my question is, if I only want to edit one element (out of many) in XML file, is there any function in RestSharp to allow me to only edit that single element, without deserializing the entire XML?
As an example, my XML:
<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<customer>
<id><![CDATA[1]]></id>
<id_default_group xlink:href="http://heatherfazelinia.com/api/groups/3"><![CDATA[3]]></id_default_group>
<id_lang xlink:href="http://heatherfazelinia.com/api/languages/1"><![CDATA[1]]></id_lang>
<newsletter_date_add><![CDATA[2013-12-13 08:19:15]]></newsletter_date_add>
<ip_registration_newsletter></ip_registration_newsletter>
<last_passwd_gen><![CDATA[2014-06-20 16:56:30]]></last_passwd_gen>
<secure_key><![CDATA[6a9b9eab95448d74a026b869d8cd723e]]></secure_key>
<deleted><![CDATA[0]]></deleted>
<passwd><![CDATA[6028853eb1033578f7432015042fa486]]></passwd>
<lastname><![CDATA[DOE]]></lastname>
<firstname><![CDATA[John]]></firstname>
<email><![CDATA[pub#prestashop.com]]></email>
<id_gender><![CDATA[1]]></id_gender>
<birthday><![CDATA[1970-01-15]]></birthday>
<newsletter><![CDATA[1]]></newsletter>
<optin><![CDATA[1]]></optin>
<website></website>
<company></company>
<siret></siret>
<ape></ape>
<outstanding_allow_amount><![CDATA[0.000000]]></outstanding_allow_amount>
<show_public_prices><![CDATA[0]]></show_public_prices>
<id_risk><![CDATA[0]]></id_risk>
<max_payment_days><![CDATA[0]]></max_payment_days>
<active><![CDATA[1]]></active>
<note></note>
<is_guest><![CDATA[0]]></is_guest>
<id_shop><![CDATA[1]]></id_shop>
<id_shop_group><![CDATA[1]]></id_shop_group>
<date_add><![CDATA[2014-08-01 13:20:37]]></date_add>
<date_upd><![CDATA[2014-08-01 13:20:37]]></date_upd>
<associations>
<groups node_type="group">
<group xlink:href="http://heatherfazelinia.com/api/groups/3">
<id><![CDATA[3]]></id>
</group>
</groups>
</associations>
</customer>
</prestashop>
I have figured out how to deserialize specific values, for example: "firstname" and "lastname".
But my current question is specifically: If I wanted to only edit "firstname" of that XML with a PUT request, would I need to deserialize and edit the entire XML? Or is there any function in RestSharp to help with that, where I can directly have it edit only the "firstname" element?
Thanks
RestSharp isn't an serialization / deserialization framework. Its a "Simple REST and HTTP API Client for .NET". It does come with an out-of-the-box features such as deserializing xml / json into proper objects (using a 3rd party framework like Json.NET).
Therefore, it cant do what you're asking, you'll have to deserialize the whole xml and change the attributes you desire.
What you need to be done can be done quite easily using LINQ 2 XML:
//Assuming you get your xml as a string:
var xml = XElement.Load(yourXmlString);
var firstName = xml.Element("customer").Element("firstname");
var lastName = xml.Element("customer").Element("lastname");
firstName.Value = "firstChange";
lastName.Value = "secondChange";
var returnedXml = xml.ToString();
Of course, you'll have to add nullity checks, exception handling, etc.

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"

Format WCF Response

I have a object return in a WCF and when I do an xml over http the response will look like:
<person>
<name>Hello</name>
</person
I need it to look like
<?xml version="1.0" encoding="UTF-8"?>
<pre:person>
<name>Hello</name>
</pre:person>
Is there an easy way to do it in C#?
Glance over this article it may help you Changing prefixes in XML responses for WCF services.
Or you can try to return XElement.

Categories