服务引用未生成客户端类型

31

我正在尝试通过向其添加服务引用来在类库中使用 WCF 服务。其中一个类库可以正常消耗它,我可以访问客户端类型以生成代理。然而,在我的第二个类库(或甚至在控制台测试应用程序中),当我添加相同的服务引用时,它只公开与契约操作有关的类型,并没有客户端类型让我可以生成代理来使用那两个契约中公开的操作。

例如,终结点公开了2个服务 - ISvc1 和 ISvc2。当我在第一个类库中向此终结点添加服务引用时,我得到了 ISvc1Client 和 ISvc2Client 来生成代理,以便使用这两个契约公开的操作。除了这些客户端,服务引用还公开了涉及操作的类型(例如 Type 1、Type 2 等)。这就是我需要的。然而,当我尝试在另一个控制台应用程序或类库中添加服务引用到相同的终结点时,仅公开 Type 1、Type 2 等,而不是 ISvc1Client 和 ISvc2Client,因此我无法生成代理来访问我的目标操作。我无法确定为什么一个类库可以正确生成服务引用,而另一个类库或测试控制台应用程序却不能。


1
我不太明白,您是说第一个创建服务引用的应用程序获取客户端对象,而后续的应用程序则没有获取到吗?这听起来有些不合理,您能否澄清一下,并/或者提供一些代码? - Greg Olmstead
7个回答

54
您可能已选择了在指定的引用程序集中重用类型,但未选择非常重要的mscorlib库。
首先,在解决方案资源管理器顶部单击“显示所有文件”,以便您可以展开服务引用。
找到Reference.cs文件并打开它。在源代码中搜索ClientBase,以确保您确实没有生成意外名称的客户端。如果找到它,那就是您的服务客户端的名称。
如果没有找到匹配项,则右键单击服务引用并选择配置服务引用
重要的一个是mscorlib ,它需要正确生成客户端。我喜欢选择System.Xml.Linq,也可以获得漂亮的Linq类,如XElement而不是XmlElement
仍然卡住了吗?
提示:我总是更喜欢为服务引用创建一个专用的DLL。如果您需要清除它并重新开始,这可以帮助您,而且可以避免某些鸡和蛋编译问题。
如果最终只有一半的References.cs文件,则您可能正在“重用引用的类型”,但这些类型与您的数据契约不兼容。即您已在服务器端添加了数据成员,或者更改了现有成员的签名,例如使值类型可选。
首先,要意识到SVCUTIL即使存在问题也会愉快地生成不完整的输出文件,并且在从Visual Studio运行时您不会得到日志文件。在资源管理器中注意预期大小并将其与“上次已知的良好大小”进行比较。
尝试直接从批处理文件中运行SVCUTIL.EXE(记得保存此文件以供下次使用)
这在Visual Studio命令提示符中最容易完成。
示例命令如下,请注意 reference 参数是引用类型的DLL。
svcutil.exe http://dev.example.com/SSWPF.Web/Services/SS.svc /reference:bin\debug\RRStore.Sys.DLL
Detail: An exception was thrown while running a WSDL import extension:

System.ServiceModel.Description.DataContractSerializerMessageContractImporter 错误:在命名空间 'http://schemas.datacontract.org/2004/07/SS.Sys' 中,具有数据契约名称 'ShippingRateInfo' 的引用类型 'SS.Sys.ShippingRateInfo, RRStore.Sys, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 无法使用,因为它与导入的 DataContract 不匹配。需要从引用类型中排除此类型。
XPath 错误源://wsdl:definitions[@targetNamespace='http://tempuri.org/']/wsdl:portType[@name='ISSWCF']

幸运的是,这里的答案很简单,我的类型 ShippingRateInfo 发生了改变,但我没有更新它。一旦我从服务器复制了这个类型,一切都编译得很好(我选择回退到 VS 工具)。


2
我的问题是通过简单地取消“在引用的程序集中重用类型”来解决的。某些内容正在取消一些类。 - Mike Cheel
注意:似乎并不需要使用System.ServiceModel。我想它知道该如何使用。 - Simon_Weaver
1
兄弟,你是我的新神。我找到了clientBase,但类的名称与我预期的不同。非常感谢。 - Guillermo Varini

8

实际上,如果您正在使用服务契约上的KnownTypeAttribute对类型进行序列化,则必须在您要添加服务引用的项目中包含对类型库的引用。

例如,如果您的WCF服务对类型System.Drawing.Image进行序列化,则使用方项目必须引用System.Drawing。希望这能帮助一些人。


4
很让人恼火的是它根本不显示任何错误 - 只生成了一个非常简略的代理版本。 - Zar Shardan

5
我曾遇到类似问题,原因是类型不匹配。这导致我无法在测试项目中生成客户端。我们维护不同版本的合同,在创建新版本时,我引入了类型不匹配的错误。以下是我的情况下的代码场景。
第1个版本的合同:
[DataContract(Namespace="http://www.exmample.com/v1")]
public enum Fruits
{
    [EnumMember]
    Apple,
    [EnumMember]
    Orange
}

版本2合同

[DataContract(Namespace="http://www.exmample.com/v1")]
 public enum Fruits
 {
    [EnumMember]
    Apple,
    [EnumMember]
    Orange,
    [EnumMember]
    Mango
 }

我使用命令行工具svcutil解决了这个问题。 命令:
svcutil MyContract.dll

我收到了以下错误信息。
DataContract for type 'V2.Fruits' cannot be added to DataContractSet since type 'V1.Fruits with the same data contract name 'Fruits' in namespace 'http://www.exmample.com/v1' is already present and the contracts are not equivalent.

我将命名空间从版本1更改为版本2,然后在测试项目中成功生成了服务引用。

[DataContract(Namespace="http://www.exmample.com/v2")]
 public enum Fruits
 {
    [EnumMember]
    Apple,
    [EnumMember]
    Orange,
    [EnumMember]
    Mango
 }

使用svcutil可以帮助解决此问题。


2

我也遇到了同样的问题。原来我的项目直接引用了一个DLL而不是项目引用。所以即使我的项目已经引用了这个程序集,但它引用的是旧版本。一旦我更新了DLL并更新了服务引用,一切都恢复正常了。


1

这通常发生在添加之前已经添加过的服务引用时。在客户端配置中,它仍然具有相关的servicemodel。确保从客户端配置中删除servicemodel,然后再尝试重新添加服务引用!


1

和 @Kevin 的回答类似,我在服务项目中添加了对所有项目和 DLL 的引用。然后代理生成程序就能够识别/生成所需的类型。

完成这些步骤后,您甚至可以开始删除一些冗余的引用并重新生成项目。


-5
显然,在添加服务引用之前,您需要在项目中添加对 System.Web 的引用。这样就可以了。

4
没帮到我,问题还是一样! - bychkov
这很奇怪,因为我的成功生成的代理在 Reference.cs 文件中甚至没有 System.Web... - Simon_Weaver

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