Reputation: 19902
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
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
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
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:
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 "$(DataContractGeneratedFilePath)"" />
<Exec
Condition="'@(DataContractItems)' != ''"
Outputs="$(DataContractGeneratedFilePath)"
Command=""$(WIN_SDK_PATH)bin\SvcUtil.exe" @(SvcUtilParam, ' ') @(GenerateDataContracts -> '%(DataContractSchemaMapping)') "/out:$(DataContractGeneratedFilePath)" "%(DataContractItems.FullPath)"" />
</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
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