parse string from soap and fetch data, c# - c#

I have an issue parsing through some XML in C#.
My XML is this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetArticleByIDResponse xmlns="namespace_1">
<GetArticleByIDResult xmlns:a="namespace_a" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:ArticleHeader>Header text here</a:ArticleHeader>
<a:Content>Content here</a:Content>
</GetArticleByIDResult>
</GetArticleByIDResponse>
</s:Body>
</s:Envelope>
How Can I get the content and article header from that XML when parsed as in as a string. I have tried so many examples, and failed all of them.
It doesnt matter if its linq or XmlDocument. Just need a scenario, where I can grab the content and actually use it.

Using LINQ-to-XML :
XNamespace a = "namespace_a";
XDocument doc = XDocument.Parse("your xml string here");
var header = (string)doc.Root.Descendants(a + "ArticleHeader").FirstOrDefault();
var content = (string)doc.Root.Descendants(a + "Content").FirstOrDefault();

Adding to my comment the .Net Soap System is bugged or just flaming wrong as it does not support using xmlns as a namcespace for some stupid reason i have spent many hours with this problem from a php client to a .Net Server to correct try this.
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<GetArticleByIDResponse xmlns="namespace_1">
<GetArticleByIDResult>
<ArticleHeader xmlns="namespace_a">Header text here</ArticleHeader>
<Content xmlns="namespace_a">Content here</Content>
</GetArticleByIDResult>
</GetArticleByIDResponse>
</Body>
</Envelope>
i think that should work for if you should be using php to send to soap i have a fix on a feature/bug request with php https://bugs.php.net/bug.php?id=64704&edit=3 that will correct the problem with php if your using another soap client request builder you will need to see if you can tell it to use in-line namespacing insted of named/taged namespacing (i think thats what they call it but i cant be certain)

Related

How to create a method in a ASMX Web Service with nested values

I am creating a web service to receive data from another source which will have the following format when the request is made.
The SOAP request for the call has been provided (see below) so I need to accept the data in this format. It is also going into an existing set of web services which can not be updated at this time. They are written in C# using the older style WSDL Web Service.
<?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>
<GetDepartmentData xmlns="webservice.localhost/">
<ID>123</ID>
<Name>John Smith</Name>
<Departments>
<DepartmentID>1</DepartmentID>
<DepartmentID>2</DepartmentID>
<DepartmentID>4</DepartmentID>
</Departments>
<Phone>0123456789</Phone>
</GetDepartmentData>
</soap:Body>
</soap:Envelope>
I need to take this request then extract all the data and send into a SQL stored procedure for processing.
Everything is pretty straight forward apart from the 'Departments' section as I am unsure of the correct data type to use and how best to handle this as all the other web service just have single non-complex data types.
The code for the method is as follows:
[WebMethod]
public string GetDepartmentData(int ID, string Name, ???? Departments, string Phone)
{
// Do something with the input here
}
My plan is to convert the Departments into either a XML data type which I can send into SQL and then split into a table or create a delimited string from the DepartmentID values and then split that in SQL. Not sure yet but that will be the easier part.
The problem I am having is I am unsure of the best way to create the method to handle the SOAP request I am being sent.
Thanks.

How to generate Soap Envelope and body for a class generated using XSD.exe in C#

I have one XSD which in turn use multiple XSDs. I have generated .cs file using XSD.exe. Webservice Operation which i would like to call expect request XML is of this class type. Problem i am facing is that host of this webservice expect a XML with soap envelope and Soap Body. When i have generated XML using serializing the object of .cs file, it does not have soap envelope and body.
I have tried finding this on net but nothing fruitful found.
Expected XML:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken><wsse:Username>testuser</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">testwelcome1</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header>
<soap:Body xmlns:ns1="http://capabilities.nat.bt.com/xsd/EDM/EMP/ManageDocument/CreateFolder">
<ns1:CreateFolderRequest xmlns:ns2="http://wsi.nat.bt.com/2005/06/StandardHeader/" xmlns:ns3="http://capabilities.nat.bt.com/xsd/EDM/EMP/ManageDocument/Header/1.0">
<ns2:standardHeader>
<ns2:serviceState>
<ns2:stateCode>OK</ns2:stateCode>
</ns2:serviceState>
<ns2:serviceAddressing>
<ns2:from>Dummy</ns2:from>
<ns2:to>
<ns2:address>Dummy/ns2:address>
</ns2:to>
<ns2:replyTo>
<ns2:address>Dummy</ns2:address>
</ns2:replyTo>
<ns2:messageId>MessageID1</ns2:messageId>
<ns2:serviceName>Dummy</ns2:serviceName>
<ns2:action>AddDocumentRequest</ns2:action>
</ns2:serviceAddressing>
</ns2:standardHeader>
<ns3:HeaderRequest>
<ns3:AccountID>sharePoint_user</ns3:AccountID>
<ns3:Password>Dummy</ns3:Password>
<ns3:Domain>Dummy</ns3:Domain>
</ns3:HeaderRequest>
<ns1:RepositoryID>Dummy</ns1:RepositoryID>
<ns1:FolderName>test_test_test_1</ns1:FolderName>
<ns1:ParentID>null</ns1:ParentID>
<ns1:CreatedDate>2012-03-02</ns1:CreatedDate>
<ns1:OwnerID>null</ns1:OwnerID>
<ns1:ParentPath>Test_Folder</ns1:ParentPath>
</ns1:CreateFolderRequest>
</soap:Body>
</soap:Envelope>
Please help. sorry but i am new to this SOAP thing.

C# Parsing Response of a Java Web Service

I am calling a Java WebLogic web service from my .Net application. I have added a service reference to the jws service.
The service can be called fine and I can see the response in Fiddler, however the problem is that the propery listOfHolds is coming as null although I can see a list of holds in the XML of the response.
Here is the code for calling
holdsList result = proxy.viewHoldsList(request.AccountNo);
int noOfHolds = result.NumberOfHolds; // This value is read fine
object[] holds = result.listOfHolds; // This is coming as Null despite the values in the response
Here is the response XML as captured by Fiddler
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header>
<work:WorkContext xmlns:work="http://oracle.com/weblogic/soap/workarea/">rO0...AAA</work:WorkContext>
</S:Header>
<S:Body>
<ns0:viewHoldsListResponse xmlns:ns0="http://www.openuri.org/">
<ns0:viewHoldsListResult>
<ns0:TotalAmount>130.0</ns0:TotalAmount>
<ns0:NumberOfHolds>4</ns0:NumberOfHolds>
<ns0:listOfHolds>
<ns0:item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns0:holdDetails">
<ns0:xsiType>HoldDetails</ns0:xsiType>
<ns0:Amount>100.0</ns0:Amount>
<ns0:StartDate>2014-02-15T00:00:00.0</ns0:StartDate>
<ns0:ExpiryDate>2014-02-20T00:00:00.0</ns0:ExpiryDate>
<ns0:Description>For testing</ns0:Description>
<ns0:Instruction/>
<ns0:Tracer>00000810000287294002</ns0:Tracer>
<ns0:HoldId>3591376655</ns0:HoldId>
<ns0:EmployeeId>0</ns0:EmployeeId>
</ns0:item>
<ns0:item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns0:holdDetails">
<ns0:xsiType>HoldDetails</ns0:xsiType>
<ns0:Amount>10.0</ns0:Amount>
<ns0:StartDate>2014-02-15T00:00:00.0</ns0:StartDate>
<ns0:ExpiryDate>2014-02-17T00:00:00.0</ns0:ExpiryDate>
<ns0:Description>DESC</ns0:Description>
<ns0:Instruction/>
<ns0:Tracer>00000810000287294004</ns0:Tracer>
<ns0:HoldId>3591376656</ns0:HoldId>
<ns0:EmployeeId>0</ns0:EmployeeId>
</ns0:item>
</ns0:listOfHolds>
</ns0:viewHoldsListResult>
</ns0:viewHoldsListResponse>
</S:Body>
</S:Envelope>
I have faced a similar problem before and the problem was a missing xmlns attribute on one of the tags. In this case I am suspecting the extra <ns0:xsiType>HoldDetails</ns0:xsiType> tag that is coming under the <ns0:item> tag.
Update Even after the web service provider removed the extra <xsiType> tag, I am unable to read the listOfHolds.
My questions are:
Can I do anything in my .Net code so that I get the intended value for listOfHolds?
Can I suggest any change to the owner of the Java web service?
[Optional] Why NumberOfHolds is being successfully read from the response but not listOfHolds?
The vendor of the web service has made a change. They changed xsi:type="ns0:holdDetails" to xsi:type="ns0:HoldDetails" (H instead of h).
The point is in Java, and unlike .Net as far as I can tell, they have a control over the generated XML from the web service.

Invalid Signature Reading XML from Http Response

Preface: I've been trying to do XML signature verification on an HTTP response, and I need help! All code is .NET 4.0 using C#.
So here's what I'm trying to accomplish:
Create a signed XML document on the server
Send the signed XML as body of an HTTP response
Client receives the response and verifies that the signature is valid.
Server-side, I create the XML and load it into an XmlDocument. I then sign this XmlDocument object (using this example code from MSDN) and build a string from this signed XML. This string is what I send as the HTTP response body.
When my client application receives the response, it pulls the body of the response out and passes it to my signature verification function. This function builds an XmlDocument from the string, creates a SignedXml object from the XmlDocument, and retrieves the Signature to verify. Almost all this code is taken from MSDN as well (here).
Seems straightforward, right? Well my verification fails every time. I know that it's not a problem with the signing/verifying code. I've tested it in a separate app where the XML it loads is from a file, and it works perfectly. I'm even using the exact same XML to test my client/server code.
Thus, I believe the problem lies in the step where XmlDocument is converted to a string or the string is converted back to XmlDocument.
XmlDocument -> string -> XmlDocument
I've done the following things to try to make it easier to the signature to verify:
Remove all tabs, newlines, carriage returns from the XML before I create the XmlDocument.
Ensured that the encoding of the document is explicitly set at UTF-8 (i know from previous threads that this can cause an issue if not set).
Tried generating the strings in two different ways (from OuterXML of the XmlDocument & also by using XmlWriter and StringWriter).
Visually verified that the XML sent from the server is the exact same as that loaded by the client.
If you have any idea on how to remedy this problem, please help! I can post code if desired, but the only code that might be worth seeing is how I generate the string from the XmlDocument.
An old question but I figured I would would answer it for anyone else who might have encountered a similar issue. The problem was in the encoding of the string as it was sent back via the HTTP response. However, I remedied this by writing the XmlDocument directly to the response stream instead of converting it to a string first. Like such:
public void ProcessRequest(HttpContext context)
{
// a bunch of request handling logic
//...
HttpResponse response = context.Response;
XmlDocument signedXML = getTheSignedXMLData(); //the XML
signedXML.PreserveWhitespace = true;
signedXML.Save(response.Output);
}
This solved by encoding issues and the signature verifies correctly.

.Net - Consuming webservice without WSDL

We have a new accounting system that provides webservice interface to external clients. I want to access one of the interfaces but there's no WSDL so i created the request through the use of HttpWebRequest and it works fine.
However to ease the creation of the requests and parsing of the response i would like to create some kind of automapping function. I have the request and response structure in an XSD file. Any ideas?
Request creation:
public void SendRequest()
{
HttpWebRequest request = CreateWebRequest();
XmlDocument soapEnvelopeXml = new XmlDocument();
soapEnvelopeXml.LoadXml(#"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
++ structure type inserted here ++
</soap:Body>
</soap:Envelope>");
using (Stream stream = request.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
using (WebResponse response = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();
Console.WriteLine(soapResult);
}
}
}
Well, if you really have no way of getting hold of a proper WSDL file but have XSD:s you could probably use the xsd.exe tool to create classes that map to your request and response types.
Something like this (run this in a Visual Studio Command Prompt)
xsd.exe TheRequest.xsd /c /n:Your.Namespace
xsd.exe TheResponse.xsd /c /n:Your.Namespace
But really, try your best to find that WSDL, it will make your life a lot easier..
I recommend that you Create a WSDL - reverse engineer it, and then produce your webservices client stubs from it.
The way to do it:
Get a wire trace of the exact request and response the webservice uses. Use Fiddler or something similar.
Build a WCF service, that approximates the request and response.
Get the trace of that
Compare (3) to (1). Remember you want XML infoset equivalence. Your namespace prefixes need not be the same, for example. Your namespaces need not be declared in the same location. But, the element names need to be exactly the same, and the xmlns strings need to be exactly the same. Modify the WCF service to more closely match the original. Restart it, go to step 3. Iterate as many times as it takes.
point your WCF client to the real web service
sit back and relax.
I've done this and it works. It can be tricky if you don't have insight into how DataContract attributes affect the XML on the wire. But as you play with it, you will gain the insight pretty quickly.
But how is it possible that it is a SOAP service and there is no WSDL on the service side? It might save you a ton of work to re-double your efforts to locate the real WSDL.

Categories

Resources