Showing posts with label svcutil. Show all posts
Showing posts with label svcutil. Show all posts

Tuesday, February 16, 2010

XSD to NHibernate-WCF contract converter

Guess you want to generate a WCF Data Contract from an XSD. In this case you use svcutil with /dconly option. This tool is based on
XsdDataContractImporter, so it can convert XSD files the same way, as svcutil does it.

But what do you do if you want to persist your object with NHibernate? You cannot do this with the contract generated from svcutil. The core of the problem is, that though you can switch the collection type with the /ct: options to IList. the generated data contract will not build. Second issue is that all the properties are generated public but not virtual public as we need this for NHibernate.

As svcutil is basically a wrapper around framework classes, I slapped together a small custom XSD to Class converter that generates classes that can be directly filled with NHibernate. All the customization is encapsulated in xsdconverter.cs. So feel free to change the frontend (WPF here) to whatever you like.

90% of the code is dedicated to another feature of the generator. It is capable of generating code comments from your <xs:annotations> elements. This code is based on the code released by Xsd2Code project.

You can get it here.

Due to some unlucky limitations of System.Runtime.Serialization (see comments) using the NHibernate option the serialized object may not be valid against the schema. As long as you do not require valid XML against your schema (and you probably won't) this restriction does not matter though.

Friday, March 13, 2009

Code Comments with svcutil

Unfortunately svcutil does not create comments from your XML annotations in your XSD or service WSDL. The more complex your data model gets the more the more you will miss this feature.

Well, you can be helped now.

Injecting Code into .NET Assemblies

What you need for this kind of surgery is:
1.) Reflector
2.) Reflexil (Reflector plugin)
3.) Your DLL or custom Assembly to call some code
4.) 10 Minutes time

The patient:
svcutil.exe (C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\svcutil.exe)

The enhancement:
svcutilImportCommentExtension

Primary Mission Goal:
Pimp svcutil to create nice code comments in my DataContracts from my annotations in XSD ( /dconly Option )
Secondary Mission Goal:
Pimp svcutil to create nice code comments in my WCF proxies from my WCF Service WSDL


1.) Copy the patient

2.) Start Reflector and
a.) Open the copy of svcutil.exe
b.) Open the DLL

3.) Right click on svcutil and select "Go to entry Point".

4.) Click on Main(string[] args) in "return (int) runtime.Run();"



5.) Click on ExecuteToolMode in "return this.ExecuteToolMode(toolMode, inputModule);"

6.) Click on ImportDataContracts in "this.ImportDataContracts(inputModule);"



7.) Click on ImportDataContracts in "module.ImportDataContracts();"

8.) Click on "Tools - Reflexil 0.9"

9.) Right click Line 7 "Call .... WriteConversionErrors" and select "Create New"
Choose
Opcode: ldstr
Operand Type: string
Operand: Calling svcutil extension....

Finish with selecting "Insert before selection"

10.) Right click Line 7 which now contains our "ldstr..." and select "Create New"
Choose
Opcode: Call
Operand Type: Method Reference
Operand: svcutilImportCommentExtension - svcutilImportCommentExtension.dll - ContractGenTest - CommentWriter - Hello(System.String) : System.Void



Finish with selecting "Insert after selection"

11.) Right click Line 8 which now contains our "call Hello(..)." and select "Create New"
Choose
Opcode: ldarg.0
Operand Type: None
Operand:

Finish with selecting "Insert after selection"

12.) Right click Line 9 which now contains our "ldarg.0" and select "Create New"
Choose
Opcode: ldfld
Operand Type: Field Reference
Operand: svcutil - svcutil.exe - Microsoft.Tools.ServiceModel.SvcUtil - ImportModule - schemas : System.Xml.XmlSchemaSet

13.) Right click Line 10 which now contains our "ldfld schemas" and select "Create New"
Choose
Opcode: ldarg.0
Operand Type: None
Operand:

Finish with selecting "Insert after selection"

14.) Right click Line 11 which now contains our "ldarg.0" and select "Create New"
Choose
Opcode: ldfld
Operand Type: Field Reference
Operand: svcutil - svcutil.exe - Microsoft.Tools.ServiceModel.SvcUtil - ImportModule - codeCompileUnit : System.CodeDom.CodeCompileUnit

Finish with selecting "Insert after selection"

15.) Right click Line 12 which now contains our "ldfld codeCompileUnit" and select "Create New"
Choose
Opcode: Call
Operand Type: Method Reference
Operand: svcutilImportCommentExtension - svcutilImportCommentExtension.dll - ContractGenTest - CommentWriter - WriteComments(System.Xml.Schema.SchemaSet,System.CodeDom.CodeCompileUnit)


Finish with selecting "Insert after selection"

This is how ImportDataContracts should look like now....

(Note that the Dissambler part should still display the unchanged code as we did not save it yet. This screenshot is taken from a already modified version...)

Now click on the symbol "svcutil.exe" in the reflector and select "Save as". You will now get a warning that svcutil is a signed assembly. Select "Remove Strong Name - Remove Strong Name and update referencing assemblies" and both windows. Now select "Save as" again and replace the file.

Now when you call svcutil you should get....



and have some nice comments in your code collected from all your

<xs:annotation>
<xs:documentation>.....</xs:documentation>


tags.


Sweet.

If you do the same for ImportServiceContracts() function you will be even able to create fully documented WCF proxies....

Just make sure you this time you call

CommentWriter.WriteComments(WsdlImporter importer, CodeCompileUnit compileUnit)

using the

Operand: svcutil - svcutil.exe - Microsoft.Tools.ServiceModel.SvcUtil - ImportModule - wsdlImporter: System.ServiceModel.Description

instead of the SchemaSet.

This is how ImportServiceContracts should look like after your surgery...



To bad comments don't get exported in WCF WSDL's? Well think again and get WCFExtras. A very nice WCF Extension to get XMLComments into WCF WSDL's as well as a working flat WSDL and support for Soap Headers.

Mission accomplished

Tuesday, November 18, 2008

Bug in Visual Studio 2008 WSDL Interpreter

When I started working with Flat-WSDL we soon came to a phenomenon where our list types suddenly become converted to

ArrayType[]

instead of

List<arraytype>

It took a while to drill down the cause to the following.

A common wsdl:types section looks like this:

<wsdl:types>
<xsd:schema>
</xsd:schema ....>
<xsd:schema>
</xsd:schema ....>
</wsdl:types>

but whenever there is the following section in the WSDL

<wsdl:types>
<xsd:schema ....>
</xsd:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" ....>
</xs:schema>
</wsdl:types>

you can not switch the ListTypes anymore. They will all be ArrayType[] . This applies for the ServiceReference as well as for svcutil that simply ignores the /ct: Parameter .

Both WSDL descriptions are perfectly valid as both tokens xsd: and xs: reference the http://www.w3.org/2001/XMLSchema Namespace and hence are synonyms.

I reported the bug to Microsoft using Connect (MSConnect ID:387245). But I heavily disagree with their answer, which basically says "It's not a bug it's a feature". You should find some samples wsdls there.