WCF常见类型未被重用

18

提示:这个问题有许多重复,但没有一个解决方案适用于我。

我的情况是有一个Web服务和一个客户端,它们都引用了共享程序集“DataModel”。我使用“添加服务引用…”对话框来创建服务代理,并选择“在所有引用的程序集中重用类型”,但仍然会创建新的类型而不是重用我的类型。

  • 曾经可以工作,但现在突然不再重用类型
  • 在添加服务引用之前引用共享程序集不能起作用
  • 重新启动VS2010也没有帮助(我有所有更新)
  • 我尝试了一个简单的POCO类(只是一个包含整数属性的简单类),还是没有运气
  • 删除并重新添加服务引用(或共享程序集引用)没有帮助
  • 只选择“在指定的已引用程序集中重用类型”中的共享程序集 - 没有运气
  • svcutil.exe /reference得到相同的结果

我有些无力了。还有其他解决办法吗?

编辑:我应该补充说明,我刚刚将项目重置为早期提交,无论我使用哪个提交,仍然存在相同的问题。我知道它曾经可以工作!


1
我也遇到了这个问题。我的解决方案中的问题是一个库使用了另一个 .NET Framework 版本的事实。 - Mohnkuchenzentrale
7个回答

17
引用共享程序集后再添加服务引用是不起作用的。您需要这样做,或者至少在添加引用后更新服务引用。
删除和重新添加服务引用(或共享程序集引用)没有帮助,并且您不需要这样做,但我也会尝试它。
为了使“重用”工作,两个项目(客户端和服务)都需要使用相同版本的程序集。您正在引用项目,这很好-我之前遇到过直接引用程序集因版本不同而出现问题。
以下是一些其他尝试方法:
- 为解决方案打开“配置管理器”-确保已配置共享程序集以进行构建。 - 确保客户端和服务均使用项目引用-如果服务使用较旧版本,则在客户端上使用最新程序集将无济于事。 - 删除项目引用并构建,预计构建将失败-如果未失败,则必须引用其他内容。 - 手动检查最新的“共享程序集”是否在服务和客户端中都包含在构建中-检查bin文件夹、检查程序集版本/构建日期。
如果其他方法都失败了,强制在两侧使用相同的对象的最佳方法是完全删除“服务引用”代理并使用ChannelFactory方法。请参见更简单的解释如何在不添加服务引用的情况下调用WCF服务VS2010通过直接ClientBase<>的Add Service Reference的优势。这是我首选的WCF模式,因为它消除了“更新服务引用”的需要,并删除了所有生成的代理代码。

好的建议!我已经检查了所有内容,并且共享的 DLL 在服务端和客户端中都是相同的版本。因此,我的结论是这个功能对我来说并不可靠,我将尝试使用 IChannelFactory<IMyService> 来替换代理。 - AndiDog
@AndiDog svcutil代码生成工具通常非常出色,但我个人遇到过一些问题;一旦你使用ChannelFactory模式,你就会看到它的优雅,可能再也不会回到“服务引用...” - Kirk Broadhurst
2
我现在改用 ChannelFactory<IMyService> 实现,只需很少的努力。如果合同(IMyService)可以在共享程序集中,则这确实是一个好的解决方案。谢谢! - AndiDog
1
如何更改实现以使用ChannelFactory模式?有人可以指向示例代码吗? - Shreedhar Kotekar
ChannelFactory模式在项目之间共享类型会更容易,如果您有对服务dll的引用。有关该模式的更多信息,请访问:https://msdn.microsoft.com/zh-cn/library/ms734681(v=vs.110).aspx - Steven

13

我刚刚经历了一整天的折磨,试图找出为什么在VS2013中添加服务引用时我的共享dll中的类型没有被重用。原来这个服务存在几个与序列化相关的问题。我有几个枚举没有 EnumMember 属性。我解决问题的方法是尝试以下步骤:

  1. 注释掉 ServiceContract 中所有不返回基元类型的操作(用 OperationContract 特性修饰的方法)。
  2. 然后更新客户端项目中的服务引用。当在客户端项目中输入 "[MyServiceReferenceName]." 时,我的类型没有出现在 [MyServiceReferenceName] 命名空间中,我意识到问题已经解决。我通过打开 XML Schema Browser 中生成的 XSD 文件来验证这一点,以确保它们已经重用。
  3. 逐一取消注释一个在步骤1中注释掉的方法。然后每次更新服务引用以查看是否重用类型
  4. 找到导致服务引用无法重用类型的方法, 遍历每个类,对于作为该方法的输入或输出的类型, 检查是否添加了 [DataContract] 特性。确保所有字段和属性都带有 [DataMember] 特性, 枚举也要带有 [DataContract] 和每个枚举值都要带有 [EnumMember]。

希望这能帮助正在经历这个痛苦过程的其他人。这个问题并不一定与共享 dll 有关。我的问题实际上与我的实体(模型)类没有装饰适当的属性来通知 DataContractSerializer 对这些类型进行序列化有关。似乎如果序列化的任何部分失败,则添加服务引用将添加所有类型。


1
这是我的经验:它肯定是共享类型的问题。我有3种类型 - 2个类和一个枚举,其中一个类引用另一个类的实例和枚举的一个属性。我注释掉了我添加的服务代码,然后为每个方法添加了一个带有 [OperationContract] 的虚拟方法,获取了服务并验证了是否没有副本,然后删除了该代码并取消注释以前的代码。奇怪的是,那样解决了问题。我不知道为什么,坦白说,这让我有点抓狂。 - Derreck Dean
谢谢 - 我发现了一个我忘记为其创建DataContract并为其创建EnumMembers的枚举。 - mdebeus
1
好建议。事实证明,DataContract或其缺乏也是我的问题所在。 - Rod Hartzell

2

对象套娃!

我们最近在工作中遇到了同样的问题。我们花了四个小时来查找问题,但最终发现,一个枚举类型在与拒绝复制的对象位于同一dll文件中时,它的名称与服务中使用的另一个枚举类型相同,因此它拒绝重用该dll文件中的任何类型。

建议(解决方案?): 确保dll文件中没有其他对象,或这些对象上的对象等等,与服务中的对象名称相同。


2

这有点冒险,但可能是共享dll的旧版本在全局程序集缓存中。

它试图使用共享dll,发现缺少类型的dll,然后回退到创建类型。


我根本没有使用全局程序集缓存(GAC),相反,我有一个包含所有项目的解决方案,并且正在使用项目引用。 - AndiDog

1

这是一个旧话题,但由于我今天遇到了同样的问题,所以我想分享我的解决方法。

对我来说问题是共享程序集在服务端和客户端项目中都被正确添加了,但是在服务端,这个共享程序集引用了客户端没有的另一个程序集。

我使用以下语句使用 Svcutil.exe 注意到了这个错误。在包含 SvcUtil.exe 的文件夹中打开命令行(对我而言,这是 C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools),并在更改以下部分后执行以下语句:

SvcUtil.exe /t:code /language:cs  /r:<path of the .dll that contains the types to reuse on client side> <wcf service url>

确保您想要重用的类型的 .dll 物理存在于 /bin 文件夹中(可能由于构建错误而不存在...)。如果需要,从服务中复制正确的构建。

SvcUtil 将尝试基于指定服务的 WSDL 文档生成服务和/或数据契约。/r 标记指定客户端上包含可重用类型的 .dll 的位置(就像在使用“添加服务引用”时指定的那样)。

如果重用类型存在问题,则在执行语句时会在命令行中显示。

这可以指出共享程序集中问题所在的方向。


0

在检查了所有答案后,仍然没有解决问题。然后我意识到,在浏览器中查看wsdl时,我的服务出现了错误。这很明显,对吧?嗯,事情是这样的,我以不同(非管理员)用户身份打开了服务的解决方案文件,并更新了一个可重用类型的名称。构建了我的解决方案,一切都构建成功了。这就是当我遇到OP所描述的问题时发生的事情。

发生的原因是,因为我使用的是非管理员帐户登录,并且我没有使用IIS Express。我的WCF项目没有加载。这意味着类型的重命名在WCF项目中没有生效。从而导致了问题。

简而言之,在寻找消费应用程序中的问题之前,请确保您的服务实际上已经正确启动并正常工作。


0
我想在答案列表中再添加一种情况:如果您有任何继承自共同集合的类型,例如Dictionary<K, V>,当您选择重用类型时,您需要选择在所有引用程序集中重用类型或者如果您选择在指定的引用程序集中重用类型,请确保选择包含数据契约的程序集以及System程序集(通常是泛型集合的所在地)。
在我们的情况下,我们的类定义大致如下:
public class FooMetadata : Dictionary<Guid, FooMetadataType>
{
}

其中FooMetadataType是一个[DataContract]。还要注意,您不能使用[DataContract]修饰此类,因为Dictionary已经标记为[Serializable];您的服务将编译,但在浏览到.svc文件时会出现YSOD。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接