.NET Framework Bookmark and Share   
 index > ASMX Web Services and XML Serialization > How to get nicer generated code?
 

How to get nicer generated code?

Hey all:

I have a web service that I am connecting to, but the code that Visual Studio generates is pretty ugly compared to similar code generated by AXIS2.

Here is a snippet of the schema:
<xs:elementname="thing">
<xs:complexType>
<xs:sequence>
<xs:elementminOccurs="0"maxOccurs="1"ref="cats"/>
<xs:elementminOccurs="0"maxOccurs="unbounded"ref="dogs"/>
<xs:elementminOccurs="0"maxOccurs="unbounded"ref="fish"/>
<xs:choiceminOccurs="0"maxOccurs="unbounded">
<xs:elementref="marmoset"/>
<xs:elementref="sloth"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>

And the relevant C# code:

thing.cats -> object[] (Seems to magically unwrap the "cats" container?)
thing.Items -> dogs[]
thing.Items2 -> fish[]
thing.Items3 -> object[]

For reference, the AXIS2 generated code looks like:

thing.getCats() -> Cat
thing.getDogs() -> List<Dogs>
thing.getFish() -> List<Fish>
thing.getMarmosetOrSloth() -> List<Object> (documentation shows what types can be there)

Speaking frankly, I far prefer the C# property concept over the Java get/set concept. However, the properties "Item" and "Item2" are about the most useless names possible, and make it very hard to program. Also, generating arrays as opposed to some collection makes it very hard to (for example) insert an item into the middle of the list.

Is there any way around these annoying limitations?
  • Edited byJake Goulding Thursday, October 02, 2008 3:42 PMMissing parens
  •  
Jake Goulding
I'll tell you one thing right from the start - I'm surprised that Axis2 deals with a choice element with a maxOccurs on it. It used to be the case that Axis (or JAXB) would translate that into the Java equivalent of XmlElement. The first schema I created had a choice element like that, and I couldn't get Rational Web Developer to play nice with it.

I hope you're also aware of the potential ambiguity issues that can be caused by using a choice element. Seehttp://www.w3.org/TR/xmlschema-1/#cos-nonambigand http://www.w3.org/TR/xmlschema-1/#non-ambig. These are what made me stop using choice - I don't want to have to think about things like that! They make my head hurt.

Also, having reviewed the WSDL, I have to say you'd do better if your import of urn:/animals had a schemaLocation. Here's what XMLSpy says about it:

The schema doesn't appear to be valid by itself (as a part of another schema, it might still be OK).
File ...schema2.xsd is not valid.
Unable to load schema with target namespace 'urn:/animals' from ''.
Error location: xs:schema / xs:import
Details
Unable to load schema with target namespace 'urn:/animals' from ''.

Finally, you've gotta be kidding me with this schema! Was this made up specifically to break code that interprets schemas? It's a nonsense schema. Microsoft would have to be fools to waste time making this work - it's full of things that are edge cases as best.

If you fix that schemaLocation problem, I bet you'll find that .NET handles those schemas perfectly well - as schemas. As far as translating them into code, it's a good think you don't need it, since it's not likely to ever work the way you'd like it to.

Schemas:

<types>
<xs:schemaxmlns="urn:/animals"elementFormDefault="qualified"targetNamespace="urn:/animals">
<xs:elementname="animal">
<xs:complexType>
<xs:sequence>
<xs:elementminOccurs="0"maxOccurs="1"ref="fishes"/>
<xs:elementminOccurs="0"maxOccurs="1"ref="elephant"/>
<xs:elementminOccurs="0"maxOccurs="unbounded"ref="cat"/>
<xs:elementminOccurs="0"maxOccurs="unbounded"ref="dog"/>
<xs:choiceminOccurs="0"maxOccurs="unbounded">
<xs:elementref="marmoset"/>
<xs:elementref="sloth"/>
</xs:choice>
</xs:sequence>
<xs:attributename="id"type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:elementname="fishes">
<xs:complexType>
<xs:choicemaxOccurs="unbounded">
<xs:elementref="cod"/>
<xs:elementref="tuna"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:complexTypename="cat"abstract="true">
<xs:attributename="name"type="xs:string"/>
</xs:complexType>
<xs:elementabstract="true"name="cat"type="cat"/>
<xs:complexTypename="shorthair">
<xs:complexContentmixed="false">
<xs:extensionbase="cat"/>
</xs:complexContent>
</xs:complexType>
<xs:elementname="shorthair"substitutionGroup="cat"type="shorthair"/>
<xs:complexTypename="longhair">
<xs:complexContentmixed="false">
<xs:extensionbase="cat"/>
</xs:complexContent>
</xs:complexType>
<xs:elementname="longhair"substitutionGroup="cat"type="longhair"/>
<xs:elementname="cod">
<xs:complexType>
<xs:attributename="cod"type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:elementname="tuna">
<xs:complexType>
<xs:attributename="tuna"type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:complexTypename="dog"abstract="true">
<xs:attributename="dog"type="xs:string"/>
</xs:complexType>
<xs:elementabstract="true"name="dog"type="dog"/>
<xs:complexTypename="pug">
<xs:complexContentmixed="false">
<xs:extensionbase="dog"/>
</xs:complexContent>
</xs:complexType>
<xs:elementname="pug"substitutionGroup="dog"type="pug"/>
<xs:complexTypename="collie">
<xs:complexContentmixed="false">
<xs:extensionbase="dog"/>
</xs:complexContent>
</xs:complexType>
<xs:elementname="collie"substitutionGroup="dog"type="collie"/>
<xs:elementname="elephant">
<xs:complexType>
<xs:attributename="elephant"type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:elementname="marmoset">
<xs:complexType>
<xs:attributename="marmoset"type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:elementname="sloth">
<xs:complexType>
<xs:attributename="sloth"type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>
<xs:schemaxmlns="urn:/test/types"xmlns:animals="urn:/animals"elementFormDefault="qualified"targetNamespace="urn:/test/types">
<xs:importnamespace="urn:/animals"/>
<xs:elementname="Simple">
<xs:complexType>
<xs:sequence>
<xs:elementminOccurs="0"maxOccurs="1"ref="animals:animal"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:elementname="SimpleResponse">
<xs:complexType/>
</xs:element>
</xs:schema>
</types>

John Saunders | Use File->New Project to create Web Service Projects
John Saunders
Please post the complete schema. How can we know if .NET did the right thing if we can't see what "cats" is?

Also, if you want to compare Axis2 to something from Microsoft, you should be comparing to WCF. ASMX is the past - WCF is the present and future.

John Saunders | Use File->New Project to create Web Service Projects
John Saunders
John:

Thanks for the response. You can find a pared-down version of the WSDL here:

http://dev.vivisimo.com/~goulding/naming-test.wsdl

I changed the schema around a bit, but I think you will still see my point. There are properties {Items, Items1, Items2}, which I wish were called something better.

Also, to be clear, I'm not trying to say that .NET did the "wrong" thing, just that I think it could be better.

Thanks for the pointer towards WCF. I only have VS 2005 installed, but I had a friend with 2008 create a service reference to the same file. It seemed to create the same object with the same properties, so I'm not sure that there is much gain there - although its possible we messed up :-).


Jake Goulding
I'll tell you one thing right from the start - I'm surprised that Axis2 deals with a choice element with a maxOccurs on it. It used to be the case that Axis (or JAXB) would translate that into the Java equivalent of XmlElement. The first schema I created had a choice element like that, and I couldn't get Rational Web Developer to play nice with it.

I hope you're also aware of the potential ambiguity issues that can be caused by using a choice element. Seehttp://www.w3.org/TR/xmlschema-1/#cos-nonambigand http://www.w3.org/TR/xmlschema-1/#non-ambig. These are what made me stop using choice - I don't want to have to think about things like that! They make my head hurt.

Also, having reviewed the WSDL, I have to say you'd do better if your import of urn:/animals had a schemaLocation. Here's what XMLSpy says about it:

The schema doesn't appear to be valid by itself (as a part of another schema, it might still be OK).
File ...schema2.xsd is not valid.
Unable to load schema with target namespace 'urn:/animals' from ''.
Error location: xs:schema / xs:import
Details
Unable to load schema with target namespace 'urn:/animals' from ''.

Finally, you've gotta be kidding me with this schema! Was this made up specifically to break code that interprets schemas? It's a nonsense schema. Microsoft would have to be fools to waste time making this work - it's full of things that are edge cases as best.

If you fix that schemaLocation problem, I bet you'll find that .NET handles those schemas perfectly well - as schemas. As far as translating them into code, it's a good think you don't need it, since it's not likely to ever work the way you'd like it to.

Schemas:

<types>
<xs:schemaxmlns="urn:/animals"elementFormDefault="qualified"targetNamespace="urn:/animals">
<xs:elementname="animal">
<xs:complexType>
<xs:sequence>
<xs:elementminOccurs="0"maxOccurs="1"ref="fishes"/>
<xs:elementminOccurs="0"maxOccurs="1"ref="elephant"/>
<xs:elementminOccurs="0"maxOccurs="unbounded"ref="cat"/>
<xs:elementminOccurs="0"maxOccurs="unbounded"ref="dog"/>
<xs:choiceminOccurs="0"maxOccurs="unbounded">
<xs:elementref="marmoset"/>
<xs:elementref="sloth"/>
</xs:choice>
</xs:sequence>
<xs:attributename="id"type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:elementname="fishes">
<xs:complexType>
<xs:choicemaxOccurs="unbounded">
<xs:elementref="cod"/>
<xs:elementref="tuna"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:complexTypename="cat"abstract="true">
<xs:attributename="name"type="xs:string"/>
</xs:complexType>
<xs:elementabstract="true"name="cat"type="cat"/>
<xs:complexTypename="shorthair">
<xs:complexContentmixed="false">
<xs:extensionbase="cat"/>
</xs:complexContent>
</xs:complexType>
<xs:elementname="shorthair"substitutionGroup="cat"type="shorthair"/>
<xs:complexTypename="longhair">
<xs:complexContentmixed="false">
<xs:extensionbase="cat"/>
</xs:complexContent>
</xs:complexType>
<xs:elementname="longhair"substitutionGroup="cat"type="longhair"/>
<xs:elementname="cod">
<xs:complexType>
<xs:attributename="cod"type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:elementname="tuna">
<xs:complexType>
<xs:attributename="tuna"type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:complexTypename="dog"abstract="true">
<xs:attributename="dog"type="xs:string"/>
</xs:complexType>
<xs:elementabstract="true"name="dog"type="dog"/>
<xs:complexTypename="pug">
<xs:complexContentmixed="false">
<xs:extensionbase="dog"/>
</xs:complexContent>
</xs:complexType>
<xs:elementname="pug"substitutionGroup="dog"type="pug"/>
<xs:complexTypename="collie">
<xs:complexContentmixed="false">
<xs:extensionbase="dog"/>
</xs:complexContent>
</xs:complexType>
<xs:elementname="collie"substitutionGroup="dog"type="collie"/>
<xs:elementname="elephant">
<xs:complexType>
<xs:attributename="elephant"type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:elementname="marmoset">
<xs:complexType>
<xs:attributename="marmoset"type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:elementname="sloth">
<xs:complexType>
<xs:attributename="sloth"type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>
<xs:schemaxmlns="urn:/test/types"xmlns:animals="urn:/animals"elementFormDefault="qualified"targetNamespace="urn:/test/types">
<xs:importnamespace="urn:/animals"/>
<xs:elementname="Simple">
<xs:complexType>
<xs:sequence>
<xs:elementminOccurs="0"maxOccurs="1"ref="animals:animal"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:elementname="SimpleResponse">
<xs:complexType/>
</xs:element>
</xs:schema>
</types>

John Saunders | Use File->New Project to create Web Service Projects
John Saunders
> I'll tell you one thing right from the start - I'm surprised that Axis2 deals with a choice element with a maxOccurs on it.

Yeah, basically it creates a List of Objects, but the documentation describes which objects are valid to appear in the List. It isn't the most wonderful, but it works well enough.

> Finally, you've gotta be kidding me with this schema! Was this made up specifically to break code that interprets schemas? It's a nonsense schema. Microsoft would have to be fools to waste time making this work - it's full of things that are edge cases as best.

Ouch. :-)

Honestly, no, I didn't make it up at all. In fact, it is a simplified version of our real schema. Unfortunately, most people who use web services start with a piece of code and want to make it web-accessible. We, on the other hand, are starting from XML and exposing code to that XML.

Some things that we do that are very strange from an XSD point of view. For example, we might care that an element has 2 "foo" children, but not what order they occur in:

<bar>
<foo />
<baz />
<foo />
</bar>

is as valid as

<bar>
<baz />
<foo />
<foo />
</bar>

However, this is almost impossible to describe easily with XSD.

We are making some small tweaks to our schema to better interoperate with normal programming languages.
Jake Goulding
Alternatively, don't worry about programming languages, per se. Instead, encourage your clients to send and receive XML documents.
John Saunders | Use File->New Project to create Web Service Projects
John Saunders

You can use google to search for other answers

Custom Search

More Threads

• C# -Asp.net (facing error in Connectivity through key added in web.config file)
• XmlSerializer exception when consuming response of RPC encoded Java WS in .NET 2.0
• CryptographicException: Bad Length while sending SOAP request through WSE3.0
• suppress asynchonous part of web service
• msdiscocodegenerator failed when update web reference in vs2008 for smart device application
• how do I access application variables saved in web.config file?
• InfoPath, decrese the time of execution of a web service
• Web service problem from non local computer.
• Problem on real hosting
• Viewing SOAP packet sent to a vendor's Web Service