I've added a write-up of this solution to my blog. The same information really, but perhaps a little less fragmented
I've found an alternative to using svcutil.exe
to accomplish what I want. It (imo) makes updating the service reference easier than rerunning the utility.
You should explicitly specify a namespace uri on your ServiceContract and DataContracts (see further below for comment).
[ServiceContract(Namespace = "http://company.com/MyCompany.Services.MyProduct")]
public interface IService
{
[OperationContract]
CompositeType GetData();
}
[DataContract(Namespace = "http://company.com/MyCompany.Services.MyProduct")]
public class CompositeType
{
// Whatever
}
The namespace could be anything, but technically it needs to be a valid uri, so I chose this scheme. You might have to build manually for things to work later, so do that.
Once this is done, enable the Show All Files option in the Solution Explorer. Expand the service reference you added previously. Double click the Reference.svcmap
file.
There will be a <NamespaceMappings />
element, which you will need to edit. Continuing my example:
<NamespaceMappings>
<NamespaceMapping
TargetNamespace="http://company.com/MyCompany.Services.MyProduct"
ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>
Save the file, right click the service reference and select Update Service Reference.
You can add as many mappings as you need (I actually needed two). The effect is the same as the svcutil /namespace:
approach, but without having to use the command line util itself, making for easier updating.
Difference with svcutil
The downside to this approach is that you need to use explicit namespace mappings. Using svcutil
, you have the option to map everything not explicitly mapped like this (the solution John Saunders was referring to):
svcutil /namespace:*,MyCompany.Services.MyProduct ...
You might think to use:
<NamespaceMappings>
<NamespaceMapping
TargetNamespace="*"
ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>
but this will not work, because Visual Studio already implicitly adds this mapping, pointing to the generated namespace name we're trying to get rid of. The above configuration will cause Visual Studio to complain about a duplicate key.
Ad explicit namespaces:
When no explit namespace is specified in your code, it seems that .NET will generate a uri of the form http://schemas.datacontract.org/2004/07/MyCompany.Services.MyProduct
. You could map that just as well as the explicit namespaces in my example, but I don't know if there is any guarantee for this behavior. Therefore, going with an explicit namespace might be better.
NB: mapping two TargetNamespaces to the same ClrNamespace seems to break code generation