WCF服务引用名称空间与原始名称不同

时间:2009-07-29 13:38:21

标签: c# .net wcf namespaces svcutil.exe

我的服务引用使用的命名空间有问题。我有许多WCF服务,比如命名空间MyCompany.Services.MyProduct实际名称空间更长)。 作为产品的一部分,我还提供了一个示例C#.NET网站。此Web应用程序使用名称空间MyCompany.MyProduct

在初始开发期间,该服务已添加为网站的项目参考并直接使用。我使用了一个工厂模式,它返回一个实现MyCompany.Services.MyProduct.IMyService的对象实例。到目前为止,非常好。

现在我想更改它以使用实际的服务引用。添加引用并在命名空间文本框中键入MyCompany.Services.MyProduct后,它会在命名空间 MyCompany.MyProduct.MyCompany.Services.MyProduct 中生成类。 BAD!我不想因为我正在使用代理类而在几个地方更改using指令。所以我尝试使用global::预先添加名称空间,但这是不被接受的。

请注意,我还没有删除原始程序集引用,并且启用了“重用类型”,但显然没有重用。 但是,我不希望在我的示例网站中保留程序集引用,以使其无论如何都能正常工作

到目前为止,我提出的唯一解决方案是将我的Web应用程序的默认命名空间设置为MyCompany(因为它不能为空),并将服务引用添加为Services.MyProduct。假设客户想要使用我的示例网站作为起点,并将默认命名空间更改为OtherCompany.Whatever,这显然会破坏我的解决方法。

这个问题有一个很好的解决方案吗?

总结:我想在原始命名空间中生成服务引用代理,而不引用程序集。

注意:我看过this question,但没有提供可用于我的用例的解决方案。


编辑:正如John Saunders建议的那样,我已经向微软提交了一些反馈意见: Feedback item @ Microsoft Connect

3 个答案:

答案 0 :(得分:21)

我在我的博客中添加了write-up of this solution

我找到了使用svcutil.exe来完成我想要的替代方法。它(imo)使得更新服务引用比重新运行实用程序更容易。

您应该在ServiceContract和DataContracts上明确指定名称空间uri(请参阅下面的评论)。

[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
}

命名空间可以是任何东西,但从技术上讲它需要是一个有效的uri,所以我选择了这个方案。您可能需要手动构建以便以后工作的东西,所以这样做。

完成此操作后,在解决方案资源管理器中启用显示所有文件选项。展开先前添加的服务引用。双击Reference.svcmap文件。

将有一个<NamespaceMappings />元素,您需要编辑它。继续我的例子:

<NamespaceMappings>
    <NamespaceMapping
        TargetNamespace="http://company.com/MyCompany.Services.MyProduct"
        ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>

保存文件,右键单击服务参考,然后选择更新服务参考

您可以根据需要添加任意数量的映射(实际上我需要两个)。效果与svcutil /namespace:方法相同,但无需使用命令行util本身,便于更新。

与svcutil的区别

此方法的缺点是您需要使用显式命名空间映射。使用svcutil,您可以选择映射未明确映射的所有内容(John Saunders所指的解决方案):

svcutil /namespace:*,MyCompany.Services.MyProduct ...

您可能会考虑使用:

<NamespaceMappings>
    <NamespaceMapping
        TargetNamespace="*"
        ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>

但这将工作,因为Visual Studio已经隐式添加了这个映射,指向我们试图摆脱的生成的命名空间名称。上述配置将导致Visual Studio抱怨重复的密钥。

广告明确命名空间
当您的代码中未指定explit命名空间时,似乎 .NET将生成 http://schemas.datacontract.org/2004/07/MyCompany.Services.MyProduct 形式的uri。你可以在我的例子中映射那个和显式命名空间一样,但我不知道这种行为是否有任何保证。因此,使用显式命名空间可能会更好。

注意:将两个TargetNamespaces映射到同一个ClrNamespace似乎会破坏代码生成

答案 1 :(得分:1)

您的用例错误。

您绝不应该首先将服务作为参考。

我相信svcutil.exe会接受一个指定要使用的完整命名空间的开关。

答案 2 :(得分:0)

在VS2010及更高版本中,有一种设置自定义命名空间的方法。 在解决方案资源管理器中,选择&#34;显示所有文件&#34;然后打开#34; Web引用&#34;在解决方案树中,选择服务,选择Reference.map节点,显示属性并进行设置 自定义工具命名空间属性。

不幸的是,我没有足够的声誉来展示截图。