WCF service reference namespace differs from original

余生长醉 提交于 2019-11-28 16:54:54

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

Your use case was wrong.

You should never have included the service as a reference in the first place.

I believe svcutil.exe will accept a switch specifying the full namespace to use.

In VS2010 and later versions there is a way to set up custom namespaces. In the solution explorer, select "Show all files" then open "Web references" in the solution tree, select the service, select the Reference.map node, show the properties and set the Custom Tool Namespace property.

Unfortunately I don't have enough reputation to show a screenshot.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!