I recently blogged about the much improved Add Service Reference dialog in Visual Studio 2008. If you have DataSets exposed in your web services it will still generate new Datasets from the schemas and not reuse your existing DataSets even if you have a reference to the DataSet-project. The new dialog handles this without problem for you DataContract-classes though.
The solution to the problem is to implement a SchemaImporterExtension class and for DataSets you must override the ImportSchemaType method with the most arguments, because that is what gets called for complex types like DataSets. Here is a short guide how you could do this:
- In your project with the DataSets add a new class and call it DataSetSchemaImporterExtension and let the new class inherit from SchemaImporterExtension.
- Override ImportSchemType like this:
public class DataSetsSchemaImporterExtension : SchemaImporterExtension
{
public override string ImportSchemaType(XmlSchemaType type, XmlSchemaObject context,
XmlSchemas schemas, XmlSchemaImporter importer,
CodeCompileUnit compileUnit, CodeNamespace mainNamespace,
CodeGenerationOptions options, CodeDomProvider codeProvider)
{
if (type != null)
{
foreach (XmlSchema schema in schemas)
{
const string rootNamespace = "http://YourUniqueSchemaThatAllDataSetUses/";
if (schema.TargetNamespace.StartsWith(rootNamespace))
{
mainNamespace.Imports.Add(
new CodeNamespaceImport(
typeof(AClassInTheSameNamespaceAsTheClasses).Namespace
));
return schema.Id;
}
}
}
return base.ImportSchemaType(type, context, schemas, importer,
compileUnit, mainNamespace, options, codeProvider);
}
}
- The following is worth noting about the code above. I recommend you to have a namespace other than tempuri.org for the datasets because this class will be used every time you set a reference in visual studio no matter for which project you add a reference. Change AClassInTheSameNamespaceAsTheClasses to one of your dataset classes and I use this so that the namespace string will not be hardcoded if the (.NET) namespace for the datasets changes. schema.Id will have the same string as the name of the Dataset class.
- The Dataset assembly must be available in the GAC and one easy way to ensure that after each compile is to add a post-build event with the following:
gacutil /i $(TargetPath) /f
Notice: To be able to add an assembly in the GAC it must have a strong name, which can also be set up in project properties.
- After compiling the project it's time to register the new class in machine.config so that .NET knows about it when adding service references. Open machine.config and move to the very bottom and paste the following just before the configuration endtag.
<system.xml.serialization>
<schemaImporterExtensions>
<add name="EIO.Medlemsservice.Dto"
type="DataSetProject.DataSetsSchemaImporterExtension, DataSetProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=YourPublicKey"
/>
</schemaImporterExtensions>
</system.xml.serialization>