有时,添加一个 WCF 服务引用会生成一个空的 Reference. cs

有时,添加 WCF Service Reference 会生成一个空的 Reference. cs,我不能在项目中的任何地方引用该服务。

有人遇到过这种情况吗?

118638 次浏览

一般来说,我发现这是一个代码生成器的问题,而 大部分的问题是因为我有一个无法解决的类型名称冲突。

如果您右键单击您的服务引用,然后单击 configure 和 取消检查 “在引用的程序集中重用类型”,那么问题很可能就解决了。

如果您正在使用这个特性的某些方面,那么您可能需要确保您的名字被清除。

发生这种情况时,请查看“错误”窗口和“输出”窗口,以查看是否存在任何错误消息。如果这没有帮助,试着手动运行 svcutil.exe,看看是否有任何错误消息。

正如公认的答案所指出的,重用类型时的类型引用问题可能是罪魁祸首。我发现当您无法轻易确定问题时,使用 svcutil.exe 命令行将帮助您揭示潜在的问题(正如 John Saunders 指出的)。

这里的增强是使用 svcutil 的一个快速示例。

svcutil /t:code https://secure.myserver.com/services/MyService.svc /d:test /r:"C:\MyCode\MyAssembly\bin\debug\MyAssembly.dll"

地点:

  • /t: code 从给定的 url 生成代码
  • /d: 指定输出的目录
  • /r: 指定引用程序集

这里引用完整的 svcutil 命令行: http://msdn.microsoft.com/en-us/library/aa347733.aspx

运行 svcutil 后,应该会看到导入引发的异常。您可能会收到关于您的一个类型的这种类型的消息: “引用的类型不能使用,因为它不匹配导入的数据契约”。

这可以简单地按照指定的方式进行,因为引用的程序集中的一种类型与服务的 DataContact 中生成的类型有所不同。在我的示例中,我导入的服务具有来自共享程序集中的更新的类型。这一点并不明显,因为例外中提到的类型似乎是相同的。不同的是该类型使用的一种嵌套复杂类型。

还有其他更复杂的场景可能会触发这种类型的异常并导致空白 reference e.cs. 这里有一个例子

如果您正在经历这个问题,并且您没有在数据契约中使用泛型类型,也没有使用 IsReference = true,那么我建议确认您的共享类型在客户端和服务器上是完全相同的。否则,您可能会遇到这个问题。

我发现,无论何时添加引用、删除引用,然后重新添加具有相同名称的服务,都会发生这种情况。类型冲突似乎是由于 VisualStudio 仍然可以看到的旧文件仍然保留在某个位置而造成的。所有我需要做的修复它,是一个干净之前添加新的引用。

  1. 删除有问题的服务引用。
  2. 单击 解决方案资源管理器中的项目名称以突出显示该项目。
  3. 右键单击项目引用。
  4. 在上下文列表的顶部附近,单击 干净项。
  5. 像往常一样添加服务引用。

希望这个能帮上忙。

我一整天都在为这个问题绞尽脑汁,现在我已经解决了,这就是..。

要在 SSL 上运行的服务 曾经(即在 https://mydomain.com/MyService.svc)

在开发服务器上向 WCF 服务添加服务引用就可以了。

在实时生产服务器上部署与 WCF 服务构建相同的 一模一样,然后切换到客户端应用程序,并将服务引用配置为指向实时服务显示没有错误,但是应用程序不会构建: 原来服务引用的 Reference.cs 文件是完全空的!更新服务引用没有任何区别。清洗溶液没有帮助。重新启动 VS2010没有什么区别。创建新的空白解决方案、启动控制台项目和向实时服务添加服务引用都会出现完全相同的问题。

我不认为这是由于类型冲突或其他原因,但管他呢——我通过取消选中“在所有引用的程序集中重用类型”重新配置了 WCF 服务引用。不行,我把对号放回去了。

下一步是在引用 URL 上尝试 Svcutil,看看它是否有助于发现问题。下面是命令:

svcutil /t:code https://mydomain.com/MyService.svc /d:D:\test

这产生了以下结果:

Microsoft (R) Service Model Metadata Tool
[Microsoft (R) Windows (R) Communication Foundation, Version 4.0.30319.1]
Copyright (c) Microsoft Corporation.  All rights reserved.


Attempting to download metadata from 'https://mydomain.com/MyService.svc' using WS-Metadata Exchange or DISCO.
Error: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: Schema with target namespace 'http://mynamespace.com//' could not be found.
XPath to Error Source: //wsdl:definitions[@targetNamespace='http://mynamespace.com//']/wsdl:portType[@name='IMyService']




Error: Cannot import wsdl:binding
Detail: There was an error importing a wsdl:portType that the wsdl:binding is dependent on.
XPath to wsdl:portType: //wsdl:definitions[@targetNamespace='http://mynamespace.com//']/wsdl:portType[@name='IMyService']
XPath to Error Source: //wsdl:definitions[@targetNamespace='http://tempuri.org/']/wsdl:binding[@name='WSHttpBinding_IMyService']




Error: Cannot import wsdl:port
Detail: There was an error importing a wsdl:binding that the wsdl:port is dependent on.
XPath to wsdl:binding: //wsdl:definitions[@targetNamespace='http://tempuri.org/']/wsdl:binding[@name='WSHttpBinding_IMyService']
XPath to Error Source: //wsdl:definitions[@targetNamespace='http://tempuri.org/']/wsdl:service[@name='MyService']/wsdl:port[@name='WSHttpBinding_IMyService']




Generating files...
Warning: No code was generated.
If you were trying to generate a client, this could be because the metadata documents did not contain any valid contracts or services
or because all contracts/services were discovered to exist in /reference assemblies. Verify that you passed all the metadata documents to the tool.


Warning: If you would like to generate data contracts from schemas make sure to use the /dataContractOnly option.

我完全被难住了。尽管沉重的谷歌和得到真的相当生气,并重新考虑作为一个公共汽车司机的职业生涯,我终于考虑为什么它在开发框工作还行。会不会是 IIS 配置问题?

我同时远程进入开发和活动框,并在每一个上启动 IIS 管理器(运行 IIS 7.5)。接下来,我检查了每个机器上的每个配置设置,比较了每个服务器上的值。

还有一个问题: 在站点的“ SSL 设置”下,确保选中了“ Require SSL”,并选中客户端证书单选按钮“ Accept”。问题解决了!

如果您最近在项目中添加了一个集合,那么问题可能是由具有相同 CollectionDataContact属性的两个集合引起的:

[CollectionDataContract(Name="AItems", ItemName="A")]
public class CollectionA : List<A> { }


[CollectionDataContract(Name="AItems", ItemName="A")]  // Wrong
public class CollectionB : List<B> { }

我彻底检查了我的项目,并确保每个 姓名项目名称属性都是唯一的,从而修正了这个错误:

[CollectionDataContract(Name="AItems", ItemName="A")]
public class CollectionA : List<A> { }


[CollectionDataContract(Name="BItems", ItemName="B")]  // Corrected
public class CollectionB : List<B> { }

然后我刷新了服务引用,一切又恢复正常了。

我有这个问题与 Silverlight5从以前的版本升级。

即使重新添加服务引用,我仍然得到一个空 Reference.cs

最后,我不得不创建一个全新的项目并重新创建服务引用。 如果你花了超过半个小时在这上面,这是一个值得尝试的东西。即使您决定修复原始项目,您也可以尝试这样做,只是为了看看会发生什么,然后向后工作,尝试修复问题。

我从来没有弄清楚到底是什么问题-但可能在。Csproj 文件没有升级或者某些设置出错。

正如@dblood 指出的,主要问题在于 DataContractSerializer,它不能正确地重用类型。这里已经有了一些答案,所以我首先要补充一些正反两方面的内容:

  • ‘ IsReference’标志会带来很多麻烦,但是移除它并不总是解决问题的办法(特别是: 在使用递归的情况下)。
  • 潜在的问题是,数据契约在某种程度上不同于类型名称,即使它们有时候是(啊?是的,你没看错!).显然,序列化程序非常挑剔,很难找到真正的问题。
  • 从“配置服务引用”中删除“引用检查”是可行的,但是会留下多个实现。然而,我经常跨 DLL 重用 SOAP 接口。此外,据我所知,在大多数成熟的 SOA 中,多个服务接口实现并扩展相同的接口类。删除“使用引用类型”检查会导致不能再简单地传递对象的情况。

幸运的是,如果您控制了您的服务,那么有一个简单的解决方案可以解决所有这些问题。这意味着您仍然可以跨 DLL 重用服务接口-这是一个正确的解决方案必须具备的。解决办法是这样的:

  1. 创建一个单独的接口 DLL。在这个 DLL 中,包含所有的数据合同和服务合同; 将服务合同放在你的接口上。
  2. 从接口派生服务器实现。
  3. 使用相同的 DLL 使用您喜欢的方法构造客户端,例如(IMyInterface 是服务契约接口) :

    var httpBinding = new BasicHttpBinding();
    var identity = new DnsEndpointIdentity("");
    var address = new EndpointAddress(url, identity, new AddressHeaderCollection());
    var channel = new ChannelFactory<IMyInterface>(httpBinding, address);
    return channel.CreateChannel();
    

In other words: Don't use the 'add service reference' functionality, but force WCF to use the (correct) service types by bypassing the proxy generation. After all, you already have these classes.

Pro's:

  1. You bypass the svcutil.exe process, which means you don't have any IsReference issues
  2. DataContract types and names are correct by definition; after all, both server and client use the very same definition.
  3. If you extend the API or use types from another DLL, (1) and (2) still hold, so you won't run in any trouble there.

Cons:

  1. A-sync methods are a pain, since you don't generate an a-sync proxy. As a result, I wouldn't recommend doing this in Silverlight applications.

在我的案例中,对我有效的方法是,在看到这些答案无效之后,简单地注释掉我所有的合同,取消注释,直到它不再有效,以二进制搜索的方式。这就缩小了代码的范围。

那你只需要猜猜那个代码出了什么问题。

当然,工具中的一些错误反馈会有所帮助。

我正在写一份 Web 服务合同。我有一个没有成员的占位枚举。没关系。但是,如果我在另一个类的属性中使用它,并在客户机上重用契约 dll,那么代码生成器就会爆炸,没有错误消息。运行 svcutil.exe 没有帮助,它只是输出 cs 文件失败,没有提到原因。

这里没有列出以下内容,它是我采用的解决方案(SvcUtils 在查看错误消息时很有用。然而,我得到的错误是 wrapper type message cannot be projected as a data contract type since it has multiple namespaces。也就是说,我跟着这条线索,通过 这个的帖子了解了 wsdl.exe)。

在我的例子中,只需运行 wsdl [ My-asmx-service-address]就可以生成一个没有问题的 .cs文件,我将其包含在项目中并进行了实例化以使用该服务。

在处理双方的项目引用(服务项目和具有服务引用的项目)时,我还遇到了服务引用中断的问题。 如果。例如,引用项目的 dll 称为“ Contoso”。发展。但是项目名称简化为“ Common”,而且对该项目的项目引用也简化为“ Common”。但是,该服务需要对“ Contoso”的引用。发展。用于解析类(如果此选项在服务引用选项中被激活)。

因此,我用 Explorer 打开了项目的文件夹,其中引用了服务和“ Common”-project。在那里我编辑 VS 项目文件(。Csproj)及记事本。 搜索引用项目的名称(在本例中是“ Common.csproj”) ,您将很快找到表示项目引用的配置条目。

我变了

< ProjectReference Include = “ . . Common Common.csproj”> < 项目 > { C90AAD45-6857-4F83-BD1D-4772ED50D44C } < 名称 > 通用

< ProjectReference Include = “ . . Common Common.csproj”> < 项目 > { C90AAD45-6857-4F83-BD1D-4772ED50D44C } < 名称 > Contoso. Development. Common

重要的是将引用的名称更改为引用项目作为输出的 dll 的名称。

然后切换回 VS。您将被要求重新加载该项目,因为它已经被修改外部 VS 点击重新加载按钮。

在这样做之后,添加和更新服务引用就像预期的那样工作了。

希望这也能帮到其他人。

问候 MH

我昨天在开发过程中遇到了类似的问题。我发现我在两个不同版本的契约中使用了相同的名称空间。

我们有两个版本的契约,例如版本4和版本5。我复制了版本4中的所有契约,并将所有名称空间从版本4重命名为版本5。在执行此操作时,我忘记在其中一个文件中将名称空间从 v4重命名为 v5。由于名称空间冲突,Reference.cs 文件为空。

这个问题很难解决,因为在生成服务引用时没有收到任何错误消息。为了识别这个问题,我需要手动验证我创建的所有新文件。还有其他办法可以解决这个问题。这是在使用其他选项之前应该执行的第一步。

感谢 John Saunders 上面的帖子,它给了我一个查看“错误”窗口的想法。我一整天都在查看输出窗口是否有任何错误。

在我的案例中,罪魁祸首是 ISerialable。我有一个 DataContractclass,其 DataMember 属性类型为 Exception。不能有任何类型为具有 ISerializer 关键字的 DataMember。在这个例外有 ISerializanas 我删除它的一切工作就像一个魅力。

在尝试用 svcutil解决这个问题时,我收到了 dblood 的答案中提到的错误(“引用的类型不能使用,因为它不匹配导入的 DataContact”)。

在我的例子中,根本原因似乎是一个具有 DataContractAttribute 的枚举类型,但其成员没有标记为 EnumMember 属性。指向的问题类 svcutil有一个具有该枚举类型的属性。

这更适合作为一个评论 dblood 的答案,但没有足够的名声..。

在我的案例中,我有一个 VBWebForms 项目的解决方案,它引用了 C # UserControl。VB 项目和 CS 项目对同一个服务都有一个服务引用。该引用出现在 VB 项目中的 ServiceReferences 和 CS (框架)项目中的 Connected Services 分组下。

为了更新 VB web 表单项目中的服务引用(即,使 Reference.VB 文件不为空) ,我需要删除 CS 项目,然后更新 VB 服务引用,再将 CS 项目添加回解决方案中。

遵循以下步骤:

  1. 删除服务参考
  2. 关闭 VisualStudio
  3. 删除/Bin 和/Obj 文件夹。
  4. 开放视觉工作室。
  5. 添加服务引用。
  6. 不客气

在添加服务时,这些文件夹中似乎保留了一些引用,从而在自动生成代码期间导致错误。