Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF service + SvcUtil generating unexpected object structure

I am trying to create a WCF application that will listen for requests from a suppliers system. The supplier has provided me with a WSDL so I need to create a service and expose its' endpoint to them.

I have used SvcUtil.exe to generate the C# classes, but it outputs rather odd-looking types.

This is a snippet of the WSDL that has been given to me:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified">
      <s:element name="Submit">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="Incident">
              <s:complexType>
                <s:sequence>
                  <s:element minOccurs="0" maxOccurs="1" form="unqualified" name="TransactionId" type="s:string" />
                  <s:element minOccurs="0" maxOccurs="1" form="unqualified" name="TransactionType" type="s:string" />
                  <s:element minOccurs="0" maxOccurs="1" form="unqualified" name="TransactionSubType" type="s:string" />
                  <s:element minOccurs="0" maxOccurs="unbounded" form="unqualified" name="ConfigurationItem">
                    <s:complexType>
                      <s:sequence>
                        <s:element minOccurs="0" maxOccurs="1" form="unqualified" name="AssetTag" type="s:string" />
                        <s:element minOccurs="0" maxOccurs="1" form="unqualified" name="Name" type="s:string" />
                    ....

The command I run is simply

svcutil.exe file_name.wsdl

I would expect that this creates a structure like this:

class Submit { ... }
class Incident { ... }
class ConfigurationItem { ... }

So that when it is serialized I get something like:

<Submit>
    <Incident>
        <TransactionId>12345</TransactionId>
        <TransactionType>12345</TransactionType>
        <TransactionSubType>12345</TransactionSubType>
        <ConfigurationItem>
            <AssetTag>xyz</AssetTag>
            <Name>name</Name>
        </ConfigurationItem>
    </Incident>
</Submit>

However, the output of SvcUtil.exe gives me the following:

class SubmitIncident { ... }
class SubmitIncidentConfigurationItem { ... }

It's seems to bunch up the Submit and the Incident objects into one, and also it prepends 'SubmitIncident' onto each of the nested elements. So when serializing I get this:

<SubmitIncident>
    <TransactionId>...</TransactionId>
    <TransactionType>...</TransactionType>
    <TransactionSubType>...</TransactionSubType>
    <SubmitIncidentConfigurationItem>
        <AssetTag>...</AssetTag>
        <Name>...</Name>
    </SubmitIncidentConfigurationItem>
</SubmitIncident>

This causes problems with both the supplier (my service doesn't match their WSDL so they can't talk to me), and with onward processing I am doing in the application. Can anyone help me understand why this is happening, how to stop it, and get SvcUtil to output properly.

like image 366
Arj Avatar asked Nov 08 '22 21:11

Arj


1 Answers

TL;DR;

Do not build your WCF applications using the WCF Test Client to test them. I can't stress this enough. It forces you to remove things that will cause your application to break in normal use. Use an industry standard application like SoapUI even from the early development phase.


It turns out that the class definitions and definitions aren't really the issue here (it does cause another problem later but that's easily resolvable too once you understand what's going on). The issue was rooted in something I had done in the throwaway-development phase.

The very first thing I did was use svcutil.exe to generate the server classes using the WSDL from the supplier. Once I had enough to start debugging/testing, naturally I headed for the WCF Test Client and Visual Studio's built in development server. When using the client, it kept coming up with all sorts of obscure errors, e.g. https not supported, problems with contracts and bindings, etc. Many of them were configuration inconsistencies so were fixed with a bit of Googling, but amongst the errors was this:

The operation is not supported in the WCF Test Client because it uses type SubmitIncident

This was happening when any of SubmitIncident's properties were of type object (even if nested lower down in other properties). Basically I was just working on one error at a time, pulling out bits that didn't work until eventually it did. Mainly I was adding and removing Attributes on properties and classes, e.g. DataMember,SoapAction, Namespace, etc.

Eventually I was able to successfully invoke the endpoints in the application using the WCF Test Client. However when it came to other applications communicating to it, it was failing as per the original question. The changes I made to get it working in the WCF Test Client actually made the service invalid to the original WSDL schema!

Useful links

  • http://blogs.msdn.com/dotnetinterop/archive/2008/09/24/wsdl-first-development-with-wcf.aspx
  • http://wscfblue.codeplex.com/
like image 177
Arj Avatar answered Nov 14 '22 21:11

Arj