Generate DataContract from XSD
Asked Answered
P

4

27

I want to be able to generate a DataContract from a XSD file, preferably using the xsd.exe tool. What is the easiest way for it to auto generate the [DataContract] and [DataMember] on each of my items?

Or is there a better approach? I am trying to avoid having to recreate the data contract each time the XSD file is changed and regenerated.

Presbyopia answered 3/2, 2010 at 0:41 Comment(3)
Ok I am now getting another error. maxOccurs on DownloadRequestItem must be 1 This is my schema elementFormDefault="qualified"> <xs:element name="DownloadRequest"> <xs:complexType> <xs:sequence> <xs:element name="UserID" type="xs:string" nillable="false" maxOccurs="unbounded"/> <xs:element name="DownloadRequestItem" nillable="true"> <xs:complexType> <xs:sequence> <xs:element name="FileID" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>Presbyopia
can you please update your original question by editing it?? Putting XML into comments is REALLY REALLY hard to read and a mess.....Mendel
wcfBlue wscfblue.codeplex.comLay
M
44

The xsd.exe tool predates WCF and doesn't know anything about [DataContract] and [DataMember]. If you do use xsd.exe, you'll have to switch WCF to use the XmlSerializer instead of its default DataContractSerializer for serializing the data contracts.

The WCF equivalent for xsd.exe is svcutil.exe - it has a parameter /dconly which creates the data contracts only, from a given XSD file. This will generate a C# or VB.NET file for you, containing the data contracts nicely annotated.

Usage:

svcutil.exe (name of your XSD).xsd /dconly

This would generate a *.cs file by the same base name in your directory.

In my experience, svcutil.exe is quite picky about its XML structures - so don't be surprised if it barks at you with tons of warnings and/or errors.

Mendel answered 3/2, 2010 at 6:7 Comment(2)
Thank you I did not know this tool existedPresbyopia
quite picky about its XML structures - what DCS does and does not support is documented here msdn.microsoft.com/en-us/library/ms733112(v=vs.110).aspxEnact
W
14

Use svcutil.exe instead of xsd.exe

How to Use ? Go to Start Menu --> Microsoft Visual Studio 2008 --> Visual Studio Tools --> Visual Studio 2008 Command Prompt

and Change the directoy you want or change the directory to whre your xsd is there.

svcutil.exe /help 

it will list all the options.

one of the option I use to generate data contarct only is

svcutil.exe /target:code /n:*,[Your Company and Department].Common.DataTransferObjects /dataContractOnly /serializer:auto /importXmlTypes common.xsd /out:common.cs

Keep coding hava good day!

Wicopy answered 29/11, 2010 at 22:3 Comment(0)
J
3

DataContracts from XSD first!

It is the modern way and very good practice, however, VS2010 has very limited automation support for it. Hence, I sat down and wrote a pure msbuild target which: does not require proj file modifications and generates .g.cs. You can also achieve generating VB code very easily with small tweaks in this file.

Instalaltion: Copy the code and save it as GenerateDataContractsFromXSD.targets file into the folder 'C:\Program Files\MSBuild\4.0\Microsoft.Common.targets\ImportAfter'. This makes msbuild to read it each time it starts and same applies for VS2010.

Usage:

  • ReStart VS2010 and add an xsd into your project.
  • Select the XSD file and press F4 in order to display properties tool window.
  • Change the Build Action property to contain value GenerateDataContracts
  • Build the project with the XSD file. It generates the first .g.cs file.
  • Chnage the view in the Solution Explorer to show all files on the file system.
  • Include the new generated file in the project.
  • Add reference to System.Runtime.Serialization assembly.

Enjoy.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- Inject into the sequence of targets in order to add a generated file to compile -->
  <PropertyGroup>
    <CoreCompileDependsOn>
      GenerateDataContractsFromXSD;
      $(CoreCompileDependsOn);
    </CoreCompileDependsOn>
  </PropertyGroup>

  <ItemGroup>
    <SvcUtilParam Include="/nologo" />
    <SvcUtilParam Include="/target:code" />
    <SvcUtilParam Include="/dataContractOnly" />
    <SvcUtilParam Include="/serializer:DataContractSerializer" />
    <SvcUtilParam Include="/language:csharp" />
    <SvcUtilParam Include="/enableDataBinding" />
    <SvcUtilParam Include="/serializable" />
    <SvcUtilParam Include="/internal" />
  </ItemGroup>

  <ItemGroup>
    <AvailableItemName Include="GenerateDataContracts">
      <Targets>GenerateDataContractsFromXSD</Targets>
    </AvailableItemName>
  </ItemGroup>

  <ItemDefinitionGroup>
    <GenerateDataContracts>
      <!-- Use the following options to pass serialization options to SVCUTIL -->
      <DataContractSchemaMapping>"/n:*,$(AssemblyName).Data"</DataContractSchemaMapping>
    </GenerateDataContracts>
  </ItemDefinitionGroup>

  <!-- Automated Data Contract Serialisation using the SvcUtil.Exe tool -->
  <!-- in order to make it automated you have to set the build tool in properties window to GenerateDataContracts -->
  <Target Name="GenerateDataContractsFromXSD"
          Inputs="@(GenerateDataContracts)"
          Outputs="%(GenerateDataContracts.RootDir)\%(GenerateDataContracts.Directory)%(GenerateDataContracts.Filename).g.cs">

    <ItemGroup>
      <DataContractItems Include="@(GenerateDataContracts -> '%(FullPath)')" Condition="'%(Extension)' == '.xsd'" />
    </ItemGroup>

    <PropertyGroup>
      <DataContractGeneratedFilePath>%(DataContractItems.RootDir)\%(DataContractItems.Directory)%(DataContractItems.Filename).g.cs</DataContractGeneratedFilePath>
      <DataContractGeneratedIdentifier>@(GenerateDataContracts -> '%(RelativeDir)')%(DataContractItems.Filename).g.cs</DataContractGeneratedIdentifier>
    </PropertyGroup>

    <GetFrameworkSdkPath>
        <Output TaskParameter="Path" PropertyName="WIN_SDK_PATH" />
    </GetFrameworkSdkPath>

    <Exec 
      Condition="'@(DataContractItems)' != ''"
      Command="attrib -r &quot;$(DataContractGeneratedFilePath)&quot;" />

    <Exec
      Condition="'@(DataContractItems)' != ''"
      Outputs="$(DataContractGeneratedFilePath)"
      Command="&quot;$(WIN_SDK_PATH)bin\SvcUtil.exe&quot; @(SvcUtilParam, ' ') @(GenerateDataContracts -> '%(DataContractSchemaMapping)') &quot;/out:$(DataContractGeneratedFilePath)&quot; &quot;%(DataContractItems.FullPath)&quot;" />

  </Target>

  <Target Name="GetCopyGenerateDataContractItems"
          AfterTargets="AssignTargetPaths">
    <ItemGroup>
      <DataContractItems Include="@(GenerateDataContracts -> '%(FullPath)')" Condition="'%(Extension)' == '.xsd'" />
    </ItemGroup>

    <AssignTargetPath Files="@(DataContractItems)" RootFolder="$(MSBuildProjectDirectory)">
      <Output TaskParameter="AssignedFiles" ItemName="ContentWithTargetPath" />
    </AssignTargetPath>

  </Target>

 </Project>
Jacki answered 8/3, 2012 at 15:10 Comment(2)
You're solution is interresting but "C:\Program Files\MSBuild\4.0\Microsoft.Common.targets\ImportAfter" I don't see that folder on my computer.Tenure
@Serge, Assumptions are that you use MSBuild of .NET4 and VS2010, in this case just create the missing folder(s) and save the targets file there (msbuild internaly searches this location). This solution might work with previous MSBuild version also, if there were appropriate changes provided.Jacki
J
1

On a 64-bit machine you will find it in

%systemdrive%\Program Files (x86)\MSBuild\<version you use>

In this case:

%systemdrive%\Program Files (x86)\MSBuild\4.0\Microsoft.Common.Targets\ImportAfter\
Janinejanis answered 15/9, 2014 at 10:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.