Daveo
Daveo

Reputation: 19902

Generate DataContract from XSD

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.

Upvotes: 28

Views: 37564

Answers (4)

marc_s
marc_s

Reputation: 755321

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.

Upvotes: 44

Jacques Mostert
Jacques Mostert

Reputation: 19

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\

Upvotes: 1

pavelz
pavelz

Reputation: 31

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>

Upvotes: 3

zakirhas7
zakirhas7

Reputation: 231

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!

Upvotes: 14

Related Questions