growse
growse

Reputation: 3752

Deserialize SOAP response from webservice without WSDL

I'm trying to write a C# .NET app that can deserialize a SOAP response from a webservice. The webservice (here called 'Wibble') has no WSDL (Grrrrrrr). I have a copy of a complete sample response which I believe I can use to generate intermediate classes, but despite trying a number of different methods, I can't get a sane object from the response.

The first few lines of the response looks like this:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <ns1:inspectResponse xmlns:ns1="ProjectService" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
            <inspectReturn href="#id0"/>
        </ns1:inspectResponse>
        <multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="Wibble" id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Project">
            <category xsi:type="ns2:Category" xsi:nil="true"/>
            <classId xsi:type="xsd:long">1000000</classId>
            [...]
        </multiRef>
        <multiRef xmlns:ns3="Wibble" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id3" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns3:ProjectData">
            <author xsi:type="ns3:User" xsi:nil="true" />
            <authorUserId xsi:type="xsd:long">5289027</authorUserId>
            <classId xsi:type="xsd:long">0</classId>
            <comments xsi:type="xsd:string">Some comments.</comments>
            [...]        
        </multiRef>
    </soapenv:Body>
</soapenv:Envelope>

etc...

Firstly, if I try to use a SoapFormatter like this:

var formatter = new SoapFormatter();
var blah = formatter.Deserialize(memstream);
return blah.ToString();

I get a SerializationException: Parse Error, no assembly associated with Xml key ns1 inspectResponse

So I guess it's missing a class called inspectResponse that it can map the first element onto. So I crack out xsd.exe and generate some xsds from the XML file. From here, I generate a 52KB C# class that contains a whole bunch of code that (I'm guessing) contains all the classes that the XML file can map to. I include that, and re-run the above code and get exactly the same error.

So then I get the idea that now I have the auto-generated classes, I can just use an XmlSerializer object and try and deserialize that way. I write this:

var ss = new XmlSerializer(typeof(Classes.Envelope));
object blah;
using (var xr = XmlReader.Create(new StringReader(response)))
{
    ss.Deserialize(xr);
    blah = ss.Deserialize(xr);
}
return blah.ToString();

This time I get a new InvalidOperationException: There is an error in XML document (2, 356). ---> System.InvalidOperationException: The specified type was not recognized: name='Project', namespace='Wibble', at <multiRef xmlns=''>.

The auto-generated code doesn't contain a Project class, although it does contain a multiRef class. Presumably it's barfing because no Project class exists. I try creating a placeholder:

[Serializable]
[XmlType(TypeName = "Project", Namespace = "Wibble")]
public class Project
{
}

but that has no effect.

Am I way off the mark here, or am I just missing some small thing? I appreciate it's a fairly complex XML response with multiple multiRef elements all of different types, but I would have expected that the SoapSerializer should have been able to do something with it.

Upvotes: 3

Views: 4695

Answers (1)

Vishnoo Rath
Vishnoo Rath

Reputation: 580

Okay, why dont you try loading the response into an XMLDomDocument and use XPATH expressions or XSLT to query the nodes that you are interested in. Then a custom mapper class could map the node attributes into your POCO classes.

Just a thought and a bad work around in case you dont find anything else, but I am surprised that a SOAP return message has no WSDL to it. Is this a public service .

Have you also tried appending ?WSDL at the end of the service URL and see what happens.

Upvotes: 1

Related Questions