【问题标题】:WCF service reference namespace differs from originalWCF 服务引用命名空间与原始命名空间不同
【发布时间】:2010-11-15 01:56:12
【问题描述】:

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

在最初的开发过程中,该服务作为项目引用添加到网站并直接使用。我使用了一个工厂模式,它返回一个实现MyCompany.Services.MyProduct.IMyService 的对象实例。到目前为止,一切顺利。

现在我想更改它以使用实际的服务引用。添加引用并在命名空间文本框中输入MyCompany.Services.MyProduct 后,它会在命名空间MyCompany.MyProduct.MyCompany.Services.MyProduct 中生成类。 糟糕! 我不想仅仅因为我使用代理类而在多个地方更改using 指令。所以我尝试在命名空间前加上global::,但不被接受。

请注意,我什至还没有删除原始程序集引用,并且启用了“重用类型”,但显然没有进行重用。 但是,我不想在我的示例网站中保留程序集引用以使其正常工作

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

这个问题有好的解决办法吗?

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

注意:我见过this question,但没有提供适合我的用例的解决方案。


编辑:正如 John Saunders 所建议的,我已就此向 Microsoft 提交了一些反馈:
Feedback item @ Microsoft Connect

【问题讨论】:

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


    【解决方案1】:

    你的用例是错误的。

    您一开始就不应该将服务作为参考。

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

    【讨论】:

    • 这是一个有效的用例,但 GUI 显然不支持。自从我发布此内容以来,我一直在查看svcutil.exe 开关,它看起来会起作用。如果可以的话,我仍然想避免这样做。我还遇到了第二个问题,我使用了一个愚蠢的解决方法......当我尝试了一些选项时,我会在这里更新。
    • 我完全不同意。服务就是服务。它构建到程序集的事实不是引用程序集的借口。即使出于单元测试的目的,也不应该引用该程序集。您应该表现得好像服务是用 Java 或其他一些非 .NET 语言编写的,在这种情况下,您永远不会考虑引用程序集。
    • 哦,你指的是那部分......但是当我将它作为服务引用时,我的命名空间问题出现了。例如,生成的命名空间违反了我们使用的基于 IDesign 的编码准则。对于单元测试,我们使用ChannelFactory,它确实实际上需要一个程序集引用,但允许您轻松地将其作为测试服务托管。
    • 引用 100% ServiceContract 和 DataContract 程序集有什么问题(当然没有实现)。有什么区别,特别是如果您拥有连接的双方。我不会说这绝对是坏事,尤其是当您在项目开始时进行大量重构时,这可能会提高生产力。在这些情况下,我根本不创建服务引用。
    • 如果只是合同,我没有问题,特别是如果它们是合同,没有任何行为。我遇到的问题是他似乎引用了整个服务,包括行为。
    【解决方案2】:

    我在博客中添加了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:的方式相同,但无需使用命令行工具本身,更新更方便。

    与 svcutil 的区别

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

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

    您可能会考虑使用:

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

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

    广告显式命名空间
    如果您的代码中没有指定显式命名空间,似乎.NET 将生成 http://schemas.datacontract.org/2004/07/MyCompany.Services.MyProduct 形式的 uri。您可以像我的示例中的显式命名空间一样映射它,但我不知道这种行为是否有任何保证。因此,使用显式命名空间可能会更好。

    注意:将两个 TargetNamespace 映射到同一个 ClrNamespace 似乎会中断代码生成

    【讨论】:

    • 感谢您的详细解释。我需要控制生成对象的命名空间映射,以便将它们与部分类(在服务器和 Silverlight 客户端之间链接的文件中)配对。这样,我就有了服务生成的对象,其中包含所有的修剪以及服务器和客户端上的共享类方法和属性。
    • 在遇到此错误后,我发现这是在 SO 上发表这篇文章之前的答案,但我不得不说这样做绝对是荒谬的。 WCF 应该自动执行此操作,没有一个有效的理由要求服务的每个用户都必须手动编辑其客户端文件才能与服务通信。尽管我喜欢这样的 .NET 东西,但我对 Microsoft 非常生气。
    • @Chris:我不会认为这是一个错误。您无需任何手动编辑即可与该服务进行良好的交谈。编辑只是为了让事情符合一些个人喜好。不过,这一切都很不方便。
    • 不是错误是什么意思?如果不这样做,项目甚至无法更新其服务参考。
    • @Thorarin 讨厌在 5 年后把它带回来。这种解决方法工作得很好。然而,有一件事困扰着我。在自动生成的代码中,它仍然生成不包含代码的旧命名空间。您在编写解决方法时是否遇到过这个问题?
    【解决方案3】:

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

    很遗憾,我没有足够的声望来显示屏幕截图。

    【讨论】:

    • 我不知道这个设置,但是当我更改它然后更新服务引用时,它根本不会更改使用的命名空间。我错过了什么吗?
    猜你喜欢
    • 2012-07-08
    • 2019-04-13
    • 2021-12-28
    • 2016-05-24
    • 1970-01-01
    • 2013-03-14
    • 2016-06-14
    • 2021-01-12
    • 2013-06-25
    相关资源
    最近更新 更多