SOAP xml client - using Visual Studio 2010 c# - how? - c#

I'm new to .NET world, yet have to use VStudio C# 2010 (.NET 4.0) to produce a client that requests data from a web service in SOAP Xml fashion. I've searched here for answers but got confused even more. MSDN says that "Building XML Web Service Clients" is legacy for .NET 4.0, i.e. WSDL is legacy. Use "WCF" instead, they say.
In WCF i got lost - too much and too vague. It must be simpler then that...
And all examples that i could find on the web - they all use WSDL, "the legacy".
Here are the definitions of the service i need to use in order to obtain the data from the web service:
request:
POST /catalog.asmx HTTP/1.1
Host: www.somewebsite.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "https://www.somewebsite.com/KeywordSearch"
<?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:Body>
<KeywordSearch xmlns="https://www.somewebsite.com/">
<searchTerm>string</searchTerm>
<resultsReturned>int</resultsReturned>
</KeywordSearch>
</soap:Body>
</soap:Envelope>
Response:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?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:Body>
...some stuff...
</soap:Body>
</soap:Envelope>
So, what is the right, or at least most logical way to built this simple client? What tools/libraries/methodologies would you suggest to newbie (assuming VS 2010 C#, .NET 4.0 environment)?

If you have a WSDL/XSD to describe that service, or if you can navigate to an URL to grab that metadata, then WCF with basicHttpBinding would probably be your best bet. WSDL is definitely not "legacy" - if anything is legacy, then it's ASP.NET/ASMX webservices.
Given a WSDL/XSD or a URL where you can connect to, just do an Add Service Reference from within Visual Studio, and you should be up and running calling your WCF service in no time - trust me! You don't need to know all of WCF just to call a simple SOAP web service.... also, with WCF 4.0, lots of things - especially configuration - have been vastly improved and simplified.
As for resoures: there's the MSDN WCF Developer Center which has everything from beginner's tutorials to articles and sample code.
Also, check out the screen cast library up on MSDN for some really useful, 10-15 minute chunks of information on just about any topic related to WCF you might be interested in.

Related

OcppV1.5 over Soap Error: Action does not exist

i am currently building a Client to communicate with a Gateway of a Charge Point.
The communication is build with OcppV1.5 over Soap & Http.
The Server doesn't accept my request. I get a Http Response 500 with the Error Reason:
"XML Request is not well formed, Action does not exist."
I looked into the wsdl files but I just don't understand why it doesn't accept my action.
My Request looks something like this:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="https://www.w3.org/2005/08/addressing" xmlns:cs="urn://Ocpp/Cp/2012/06/">
<SOAP-ENV:Header>
<cs:chargeBoxIdentity>0000.0000</cs:chargeBoxIdentity>
<wsa:From>
<wsa:Address>http://000.000.000.000:0000</wsa:Address>
</wsa:From>
<wsa:To>http://000.000.000.001:0001</wsa:To>
<wsa:Action>/ChangeConfiguration</wsa:Action>
<wsa:MessageID>00000.000000000000</wsa:MessageID>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<cs:changeConfigurationRequest>
<cs:key>MeterValueSampleInterval</cs:key>
<cs:value>60</cs:value>
</cs:changeConfigurationRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Update:
As Bogdan suggested I tried to send the same message using SoapUi and it worked. The generated Request from SoapUi looks like this:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="urn://Ocpp/Cp/2012/06/">
<soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<ns:chargeBoxIdentity>000000.00000</ns:chargeBoxIdentity>
<wsa:Action>/ChangeConfiguration</wsa:Action>
<wsa:ReplyTo>
<wsa:Address>http://000.000.000.000:0000</wsa:Address>
</wsa:ReplyTo>
<wsa:MessageID>uuid:00000000-0000-0000-0000-000000000000</wsa:MessageID>
<wsa:To>http://000.000.000.000:00000/</wsa:To>
</soap:Header>
<soap:Body>
<ns:changeConfigurationRequest>
<ns:key>MeterValueSampleInterval</ns:key>
<ns:value>300</ns:value>
</ns:changeConfigurationRequest>
</soap:Body>
</soap:Envelope>
It's hard to tell from what you posted why you are getting an error, so I can only add some information that can hopefully allow you to troubleshoot the issue.
Your message has WS-Addressing headers, <wsa:Action> being one of them. The value of this field should be specified in the WSDL if your WSDL also includes WS-Addressing Metadata information, or should be specified in the documentation of the web service you are invoking. Your error message "XML Request is not well formed, Action does not exist" seems to indicate that there might be an issue with this field, but there is another action that SOAP services have which is a SOAP action. I asked about it in the comment above to make sure it's eliminated as a source of problems. In SOAP 1.1 it's called SOAPAction and is a separate HTTP header, while in SOAP 1.2 it's an action parameter on the HTTP Content-Type header. Based on the http://www.w3.org/2003/05/soap-envelope namespace, you have a SOAP 1.2 message.
With these explanations layed out, I suggest you take the WSDL and feed it to SoapUI who can generate sample requests that you can use to invoke the web service. If the WSDL also contains WS-Addressing Metadata, SoapUI should be able to pick it up and help you fill in the values you need. If not, look again through the WSDL for Action elements (make sure you differentiate between the SOAP Action and the WS-Addressing Action using their XML namespaces) or through the service documentation.
Once you get a succesfull call using SoapUI, then try to duplicate it with your code. At that point you can again use SoapUI to troubleshoot things and inspect your code built message to see it resembles the one you can successfully send with SoapUI.
Hope this helps get you closer to a resolution.

How to consume SOAP Siebel webservices in .net

Hi I am developing web application which contains Siebel web service integration. All request/response cycle will take place through XML. It is basically SOAP service. I do not have idea on siebel and soap xml. I am trying to integrate siebel service in WebAPi2. Client have provided me request and response and created sample service to test. I am able to invoke siebel service in fidler. In my webapi2 i want to integrate service.
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rol="Some Url">
<soapenv:Header/>
<soapenv:Body>
<rol:process>
<rol:IDType>National Id</rol:IDType>
<rol:Type>Customer</rol:Type>
// other parametrs
</rol:process>
</soapenv:Body>
</soapenv:Envelope>
Below is the response
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing">
<env:Header>
<wsa:MessageID>urn:some id</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:FaultTo>
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsa:FaultTo>
</env:Header>
<env:Body>
<processResponse xmlns="some url">
<result>1-198A3H</result>
<Contact_Integration_Id>1-198A3H</Contact_Integration_Id>
<SIEBEL_ERROR_CODE/>
<SIEBEL_ERRROR_MESSAGE/>
</processResponse>
</env:Body>
</env:Envelope>)
Also they have provided Public url to hit the API.
As i do not know Siebel integration in .Net and i did not find any suitable tutorial I am expecting some help from here. Any help/suggestion i get here highly appreciated. Thank you.
Although #AJPerez is correct that this is not really a Siebel issue, I would like to recommend you request for the WSDL (Web Service Definition file) from which your example message is generated. Without it you'll find it hard to use the generic .NET tutorials regarding web services.
.NET has no doubt a generator that takes a WSDL as input and generates a set of classes and functions for you to use.

XSD Namespace with different client

I have developed a web service in ASP.NET using C#. One of its web methods returns a complex type created from an xsd schema file using the xsd command.
Many client devices use this web services without a problem. WindowsMobile, PC. All are .Net applications.
Now one VB6 client needs to use this web service using SOAP Toolkit 3.0 and he has a problem probably due to the for different namespaces in the serialized xml data.
<?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:Body>
<GetProductionDataMachineryResponse xmlns="http://myFactory.it/">
<GetProductionDataMachineryResult xmlns="http://tempuri.org/XMLSchemaData.xsd">
<ResultRequest>Ok or No Data Found </ResultRequest>
.....
</GetProductionDataMachineryResult>
</GetProductionDataMachineryResponse>
</soap:Body>
</soap:Envelope>
If I remove the following annotations in the .cs file
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/XMLSchemaData.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/XMLSchemaData.xsd", IsNullable=false)]
the VB6 client works fine. But the other clients need to update the web reference.
There are over 80 other clients so this is not an attractive option.
Is there a way to get this to work with the new client without breaking the old ones?

Response from ASMX

We have an old bit of code, ASMX WebService, that we have lost the source to. I am trying to replicate the behavior of this so we can take control of it once again without affecting any of the clients.
I have created a class that mimics the behavior and properties of the response, and a soap request returns as follows
<soap:Body>
<LoginResponse>
<LoginResult>
<UserId>string</UserId>
<Password>string</Password>
</LoginResult>
</LoginResponse>
Now the service I am trying to replicate returns
<soap:Body>
<LoginRS xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<UserId>string</UserId>
<Password>Password</Password>
</LoginRS>
</soap:Body>
Now LoginRS is the name of the class I have made. My question is how do I make my response look like the second response.
I am replicating this in c# ASMX and am using the following
[WebMethod(MessageName="Login")]
public LoginRS Login(string password, string userId)
Thanks for you time.
If your objective is to reverse engineer the service, and if the service dll is with you, you can use .NET Reflector (google it) to read the dll and provide you the exact source code.

Importing Sales Orders from Magento Using C# (salesOrderList function): "There is an error in XML document (2, 372)"

Note: This question was originally part of Magento SOAP API V2 with C#: Issue with Stores that Require HTTP Authentication but I have moved a part of it here as a new question, as one part was already answered on that post.
ISSUE:
I have built a tool to import sales orders from customer stores (magento) for integration into our legacy order processing system. I have five stores to import from. Three work fine. Two of them have the following problem:
The following Exception is thrown upon executing the salesOrderList() call:
A first chance exception of type 'System.InvalidOperationException' occurred in System.Xml.dll
There is an error in XML document (2, 372).
The login succeeds, I am able to enumerate attribute values, etc.
But I am unable to run the salesOrderList() function with any
filter (and null too). It would be great if someone has experience
with this and can point me in the right direction, please.
Update: The invoking call is as follows:
salesOrderEntity[] soe = mservice.salesOrderList(mlogin, objSalesOrderFilterSet);
The Exception is, There is an error in XML document (2, 372).
The InnerException is, The specified type was not recognized: name='salesOrderListEntity', namespace='urn:Magento', at .
Fiddler showed the following requested and returned for the salesOrderList() call:
Requested:
POST /api/v2_soap/index HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 4.0.30319.239)
VsDebuggerCausalityData: uIDPoz6RG9JzwkdBniF95/gqmAcAAAAAhgJHnbvB1UOTE1y4R1Iq5VGLcSLUxTNDg57BO/4OizgACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "urn:Mage_Api_Model_Server_V2_HandlerAction"
Host: www.contoso.com
Content-Length: 1753
Expect: 100-continue
Returned:
POST http://www.contoso.com/api/v2_soap/index HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 4.0.30319.239)
VsDebuggerCausalityData: uIDPoz6RG9JzwkdBniF95/gqmAcAAAAAhgJHnbvB1UOTE1y4R1Iq5VGLcSLUxTNDg57BO/4OizgACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "urn:Mage_Api_Model_Server_V2_HandlerAction"
Host: www.contoso.com
Content-Length: 1753
Expect: 100-continue
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="urn:Magento" xmlns:types="urn:Magento/encodedTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><tns:salesOrderList><sessionId xsi:type="xsd:string">2f9c5bdc898fd92c1f61981147ee5495</sessionId><filters href="#id1" /></tns:salesOrderList><tns:filters id="id1" xsi:type="tns:filters"><complex_filter href="#id2" /></tns:filters><soapenc:Array id="id2" soapenc:arrayType="tns:complexFilter[3]"><Item href="#id3" /><Item href="#id4" /><Item href="#id5" /></soapenc:Array><tns:complexFilter id="id3" xsi:type="tns:complexFilter"><key xsi:type="xsd:string">created_at</key><value href="#id6" /></tns:complexFilter><tns:complexFilter id="id4" xsi:type="tns:complexFilter"><key xsi:type="xsd:string">created_at</key><value href="#id7" /></tns:complexFilter><tns:complexFilter id="id5" xsi:type="tns:complexFilter"><key xsi:type="xsd:string">status</key><value href="#id8" /></tns:complexFilter><tns:associativeEntity id="id6" xsi:type="tns:associativeEntity"><key xsi:type="xsd:string">from</key><value xsi:type="xsd:string">2011-12-28 00:00:00</value></tns:associativeEntity><tns:associativeEntity id="id7" xsi:type="tns:associativeEntity"><key xsi:type="xsd:string">to</key><value xsi:type="xsd:string">2011-12-28 23:59:59</value></tns:associativeEntity><tns:associativeEntity id="id8" xsi:type="tns:associativeEntity"><key xsi:type="xsd:string">in</key><value xsi:type="xsd:string">processing</value></tns:associativeEntity></soap:Body></soap:Envelope>
HTTP/1.1 200 OK
Date: Thu, 05 Jan 2012 12:11:19 GMT
Server: Apache/2.2.20 (Unix) mod_ssl/2.2.20 OpenSSL/1.0.0-fips mod_bwlimited/1.4 mod_fcgid/2.3.6
X-Powered-By: PHP/5.3.6
Content-Length: 6302
Content-Type: text/xml; charset=UTF-8
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:Magento" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:salesOrderListResponse><result SOAP-ENC:arrayType="ns1:salesOrderListEntity[1]" xsi:type="ns1:salesOrderListEntityArray"><item xsi:type="ns1:salesOrderListEntity"><increment_id xsi:type="xsd:string">100001306</increment_id><store_id
...<more data>...
xsi:type="xsd:string">John</firstname><lastname xsi:type="xsd:string">Doe</lastname><telephone xsi:type="xsd:string">999-999-9999 ext. 3333</telephone><postcode xsi:type="xsd:string">11111</postcode></item></result></ns1:salesOrderListResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
This has an easy fix, though it might take some time and you need to change some code.
The problem: You can't use the Magento WSDL address if not less than 1.6.0, as it contains weird bugs that are fixed only with 1.6, read the release notes of each version for more information
The Solution: Remove all Service References from your project and create a proxy using the svcutil.exe utility pointing to a wsdl address that is from the most recent Magento (even if you install the latest version just for this, the latest stable to this date is 1.6.1).
Then add that generated project to your web/win project and use the service from it, and swap the final url in the Client object, for example:
MyNameSpace.MagentoSoapClient ws = new MyNameSpace.MagentoSoapClient();
ws.Endpoint.Address = new System.ServiceModel.EndpointAddress("http://domain.com/api/v2_soap");
give that a try.
OKay, here goes. The service reference in the original program was created by pointing to a wsdl address under one of our Magento Go stores. The program allowed dynamically changing the shop to work with, and so the URL was changed to the relevant shop URL appended with /api/v2_soap/index at runtime.
As explained in the question, the sales order import worked for some sites and failed for others. After some pretty good advice by balexandre, we used fiddler and some on-the-spot code as needed and figured out the issue.
The Problem Was: The service call salesOrderList() returns salesOrderEntity[] for Magento Go shops and salesOrderListEntity[] for 1.5.x shops. As the proxy was created using a Magento Go reference, the latter type was "unexpected" for the program, thereby causing the Exception There is an error in XML document (2, 372) with the innerException The specified type was not recognized: name='salesOrderListEntity', namespace='urn:Magento'. All the other methods that we had invoked from the web service worked though. But without sales order listing, they weren't much useful on their own.
An Intermediate Workaround Was: To tweak the wsdl file and reference.cs to declare 'salesOrderListEntityand to create an overloaded version ofsalesOrderListEntity()`. But this workaround created more problems than it solved.
The Final Solution Is: Create two different proxies by pointing to Magento Go and Magento 1.5.x. After switching to the actual shop URLs at runtime, use the proxy relevant for the current shop. Same calls and flow, except that the first proxy knows that it will receive salesOrderEntity[] for a salesOrderList() call and the second proxy knows that it will receive salesOrderListEntity[].
This works without issues and we have imported a few hundred sales orders as I write this. And it seems to work well for 1.6.1 shops as well. But I shall let you know if (God forbid) there be any issues on that front.
On a concluding note, my sincere thanks to balexandre for all the help extended.

Categories