WCF 常见类型未重用

Posted

技术标签:

【中文标题】WCF 常见类型未重用【英文标题】:WCF common types not reused 【发布时间】:2012-01-07 09:02:40 【问题描述】:

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

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

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

不知何故,我束手无策。还有其他解决方案吗?

编辑:我应该补充一点,我只是将我的项目重置为早期的提交,无论我使用哪个提交,仍然是同样的问题。而且我知道它适用于早期的提交!

【问题讨论】:

我也遇到过这个问题。我的解决方案中的问题是一个库正在使用另一个 .NET Framework 版本 【参考方案1】:

我想我会在答案列表中添加另一种情况:如果您有任何从公共集合继承的类型,例如Dictionary<K, V>,当您选择重用类型时,您要么需要选择重用所有引用程序集中的类型,或者,如果您选择在指定的引用程序集中重用类型,请确保除了包含您的数据协定的程序集。

在我们的情况下,我们的类定义大致如下:

public class FooMetadata : Dictionary<Guid, FooMetadataType>


其中FooMetadataType[DataContract]。另请注意,您不能用[DataContract] 装饰此类,因为Dictionary 已标记为[Serializable];您的服务将编译,但在部署后,您将在浏览 .svc 文件时获得 YSOD。

【讨论】:

【参考方案2】:

在这里检查所有答案后,没有任何效果。然后我意识到我的服务在浏览器中查看wsdl时出错了。这应该很明显吧?好吧,看看发生了什么,我以不同(非管理员)用户的身份打开了服务的解决方案文件,并更新了其中一种可重用类型的名称。构建了我的解决方案,一切都成功构建。那是我遇到OP描述的问题的时候。

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

TLDR;在查找消费应用程序中的问题之前,请确保您的服务实际启动并正常工作。

【讨论】:

【参考方案3】:

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

对我来说,问题是共享程序集已正确添加到两个项目(服务和客户端)中,但在服务端,此共享程序集引用了另一个在客户端不存在的程序集。

我注意到使用带有以下语句的 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 在包含可重用类型的客户端上的位置(就像您在使用“添加服务引用”时指定的那样)。

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

这可以为您指出共享程序集存在问题的正确方向。

【讨论】:

【参考方案4】:

当我在 VS2013 中添加服务引用时,我花了一整天的时间试图找出为什么我的共享 dll 中的类型没有被重用。事实证明,该服务有几个与序列化相关的问题。我有几个没有 EnumMember 属性的枚举。我解决问题的方法是尝试以下步骤:

    注释掉所有操作(用 OperationContract 属性修饰的方法)在我的 ServiceContract 中没有返回原子类型。 然后在我的客户项目中更新我的服务参考。我意识到在我的客户项目中问题已经解决,我可以输入“[MyServiceReferenceName]”。并且我的类型没有出现在 [MyServiceReferenceName] 命名空间中。我通过在 XML Schema Browser 中打开生成的 XSD 文件来验证这一点。 逐一取消注释在步骤 1 中注释的方法。然后每次更新您的服务参考以查看类型是否被重新使用。 一旦您找到导致服务引用无法重用类型的方法,请转到每个类以查找该方法的输入或输出类型。检查您希望序列化的所有 是否都用[DataContract] 属性修饰。确保所有 fieldsproperties 都使用 [DataMember] 属性进行修饰。此外,请确保枚举使用 [DataContract] 进行装饰,并且每个枚举值均使用 [EnumMember] 进行装饰

我希望这可以帮助其他正在经历这个令人沮丧的过程的人,这个问题不一定与共享 dll 有关。我的问题并不是使用添加或更新服务参考的真正问题。问题在于我的实体(模型)类没有使用适当的属性进行装饰,以通知 DataContractSerializer 序列化这些类型。似乎如果序列化的任何部分失败,添加服务引用会添加所有类型。

【讨论】:

这是我的经验:肯定是共享类型。我有 3 种类型 - 2 个类和一个枚举,其中一个类引用另一个类的实例和枚举的一个属性。我注释掉了我添加的服务代码,然后为每个添加了一个带有[OperationContract] 的虚拟方法,得到了服务,验证了没有副本,然后删除了该代码并取消了之前的代码注释。奇怪的是,这解决了它。我不知道为什么,坦率地说,这让我有点害怕。 谢谢 - 我找到了一个我忘记创建 DataContract 并为其创建 EnumMembers 的枚举。 好建议。事实证明 DataContract 或缺少 DataContract 也是我的问题。【参考方案5】:

反对!

我们最近在我工作的地方遇到了同样的问题。我们花了四个小时来解决这个问题,但我们最终发现,与它拒绝复制的对象在同一个 dll 中的对象上的枚举与服务中使用的另一个枚举具有相同的名称,所以它拒绝重用该 dll 中的任何类型。

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

【讨论】:

【参考方案6】:

在添加服务引用之前引用共享程序集不起作用

您需要这样做,或者至少在添加参考后更新服务参考。

删除并重新添加服务引用(或共享程序集引用)没有帮助

你不应该这样做,但我也会尝试的。

为了使“重用”工作,两个项目(客户端和服务)需要使用相同版本的程序集。您正在引用该项目,这很好 - 由于版本不同,我之前在直接引用程序集时遇到过这种情况。

这里有一些其他的尝试

为您的解决方案打开“配置管理器” - 确保已将共享程序集配置为构建。 确保您对客户端 服务都使用项目引用 - 如果服务使用的是旧版本,则在客户端上使用最新程序集将无济于事。 删除项目引用并构建,并期望构建失败 - 如果它没有失败,那么您必须引用其他内容。 手动检查最新的“共享程序集”是否包含在服务和客户端的构建中 - 检查bin 文件夹,检查程序集版本/构建日期。

如果所有其他方法都失败了,强制双方使用相同对象的最佳方法是完全删除“服务引用”代理并使用 ChannelFactory 方法。请参阅 Simpler Explanation of How to Make Call WCF Service without Adding Service Ref 和 VS2010 Advantages of Add Service Reference over direct ClientBase<>。这是我首选的 WCF 模式,因为它消除了“更新服务引用...”的需要,并删除了所有生成的代理代码。

【讨论】:

好建议!检查了所有这些,共享的 DLL 在服务和客户端中都是相同的构建。所以,我的结论是这个功能对我来说不够可靠,我会尝试用IChannelFactory&lt;IMyService&gt; 解决方案替换代理。 @AndiDog svcutil codegen 工具通常非常好,但我自己也遇到了一些问题;一旦你使用 ChannelFactory 模式,你就会看到它的优雅,并且可能永远不会回到“服务参考...” 我现在更改了我的实现以使用ChannelFactory&lt;IMyService&gt;,几乎没有任何努力。如果合同(IMyService)可以在共享程序集中,这确实是一个很好的解决方案。谢谢! 如何更改实现以使用 ChannelFactory 模式?谁能指出我的示例代码。 ChannelFactory 模式更容易在项目之间共享类型,如果你有参考服务 dll。有关该模式的更多信息:msdn.microsoft.com/en-us/library/ms734681(v=vs.110).aspx【参考方案7】:

这有点远,但一种可能是旧版本的共享 dll 在 GAC 中。

它尝试使用共享 dll,找到类型缺失的 dll,然后恢复创建类型。

【讨论】:

我根本没有使用 GAC,而是我的所有项目都有一个解决方案,并且正在使用项目引用。

以上是关于WCF 常见类型未重用的主要内容,如果未能解决你的问题,请参考以下文章

重用 WCF 服务客户端

WCF ChannelFactory 和通道 - 缓存、重用、关闭和恢复

WCF 服务参考生成自己的合约接口,不会重用我的

将 WCF 转换为 WEB API:在 WEB API 中使用包装器重用 WCF 服务是个好主意吗?

如果我有一个来自Web API 2项目的身份验证过滤器,我可以在WCF服务中重用它吗?

在 GraphQL 中重用输入类型作为片段 [重复]