代码之家  ›  专栏  ›  技术社区  ›  Thorarin

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

  •  12
  • Thorarin  · 技术社区  · 15 年前

    我的服务引用使用的名称空间有问题。我有很多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 但是,如果我的用例可以接受的话,就没有解决方案。


    编辑:正如约翰桑德斯建议的那样,我已经向微软提交了一些关于这方面的反馈:
    Feedback item @ Microsoft Connect

    3 回复  |  直到 7 年前
        1
  •  21
  •   Thorarin    15 年前

    我添加了一个 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投诉重复的密钥。

    AD显式命名空间 :
    如果代码中没有指定explit命名空间,则 似乎 该.NET将生成表单的URI http://schemas.datacontract.org/2004/07/MyCompany.Services.MyProduct . 在我的示例中,您可以将其映射为显式名称空间,但我不知道是否有任何保证可以实现这种行为。因此,使用显式名称空间可能更好。

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

        2
  •  1
  •   John Saunders    15 年前

    你的用例错了。

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

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

        3
  •  0
  •   Sergiu Cosciug    7 年前

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

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