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

问题描述 投票:151回答:16

有时添加WCF服务引用会生成一个空的reference.cs,我无法在项目的任何位置引用该服务。

有没有遇到过这个?

c# .net wcf
16个回答
370
投票

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

如果右键单击服务引用并单击“配置”并取消选中“重用参考程序集中的类型”,则可能会解决该问题。

如果您使用此功能的某些方面,则可能需要确保清除名称。


1
投票

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

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


0
投票

正如@dblood指出的那样,主要的痛苦在于DataContractSerializer,它不能正确地重用这些类型。这里已经有了一些答案,所以我首先要添加一些关于这些的专业知识和缺点:

  • 'IsReference'标志会带来很多麻烦,但删除它并不总是答案(特别是:在递归的情况下)。
  • 根本问题是数据合同在某种程度上与类型名称不同,即使它们有时是(嗯?是的,你读得对!)。显然序列化器非常挑剔,很难找到真正的问题。
  • 从“配置服务引用”中删除“引用检查”有效,但是您可以使用多个实现。但是,我经常在DLL中重用SOAP接口。此外,在我所知道的大多数成熟的SOA中,多个服务接口实现并扩展相同的接口类。删除“使用引用类型”检查会导致您无法再简单地传递对象。

幸运的是,如果您掌控自己的服务,那么有一个简单的解决方案可以解决所有这些问题。这意味着您仍然可以跨DLL重用服务接口 - 这是IMO必须具备的正确解决方案。这就是解决方案的工作原理:

  1. 创建一个单独的接口DLL。在该DLL中,包括所有DataContract和ServiceContract;将ServiceContract放在您的界面上。
  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();

换句话说:不要使用“添加服务引用”功能,但强制WCF绕过代理生成来使用(正确的)服务类型。毕竟,你已经有了这些课程。

Pro的:

  1. 您绕过svcutil.exe进程,这意味着您没有任何IsReference问题
  2. 根据定义,DataContract类型和名称是正确的;毕竟,服务器和客户端都使用相同的定义。
  3. 如果您扩展API或使用其他DLL中的类型,(1)和(2)仍然保持,那么您将不会遇到任何麻烦。

缺点:

  1. A-sync方法很麻烦,因为您不生成同步代理。因此,我不建议在Silverlight应用程序中执行此操作。

0
投票

在双方使用项目引用时(服务项目和引用该服务的项目),我也遇到了服务引用中断的问题。例如,如果引用项目的.dll名为“Contoso.Development.Common”,但项目名称只是缩写为“Common”,则对该项目的项目引用也仅命名为“Common”。但是,该服务需要引用“Contoso.Development.Common”来解析类(如果在服务引用选项中激活了此选项)。

因此,对于资源管理器,我打开了引用服务和“公共”项目的项目文件夹。在那里我使用记事本编辑VS项目文件(.csproj)。搜索引用项目的名称(在此示例中为“Common.csproj”),您将快速找到表示项目引用的配置条目。

我变了

<ProjectReference Include="..\Common\Common.csproj"> <Project>{C90AAD45-6857-4F83-BD1D-4772ED50D44C}</Project> <Name>Common</Name> </ProjectReference>

<ProjectReference Include="..\Common\Common.csproj"> <Project>{C90AAD45-6857-4F83-BD1D-4772ED50D44C}</Project> <Name>Contoso.Development.Common</Name> </ProjectReference>

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

然后切换回VS.在那里,您将被要求重新加载项目,因为它已在VS之外进行了修改。单击“重新加载”按钮。

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

希望这也有助于其他人。

关心MH


0
投票

我在开发过程中遇到了类似的问题。我发现我在2个不同版本的合同中使用了相同的命名空间。

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

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


0
投票

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

在我的情况下,罪魁祸首是ISerializable。我有一个DataContract类,其DataMember属性类型为Exception。您不能拥有任何具有ISerializable关键字的DataMember类型。在这个例外中,一旦我删除了它就像ISerializable一样,它就像魅力一样。


0
投票

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

在我的情况下,底层原因似乎是具有DataContract属性的枚举类型,但其成员未标记EnumMember属性。 svcutil指出的问题类有一个枚举类型的属性。

这样可以更好地作为对dblood答案的评论,但对此没有足够的代表......


0
投票

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

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


37
投票

正如接受的答案所指出的,重用类型时的类型引用问题可能是罪魁祸首。我发现当你无法轻易确定问题时,使用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:代码从给定的url生成代码
  • / d:指定输出的目录
  • / r:指定引用程序集

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

运行svcutil后,您应该会看到导入引发的异常。您可能会收到有关您的某种类型的此类消息:“由于引用的类型与导入的DataContract不匹配,因此无法使用引用的类型”。

这可以简单地指定,因为引用的程序集中的一个类型与服务的DataContract中生成的类型存在差异。在我的例子中,我导入的服务具有更新的,更新的类型,来自我在共享程序集中的类型。这一点并不明显,因为例外中提到的类型似乎是相同的。不同的是该类型使用的嵌套复杂类型之一。

还有其他更复杂的方案可能会触发此类异常并导致空白的reference.cs。 Here is one example

如果您遇到此问题且未在数据协定中使用泛型类型,也未使用IsReference = true,那么我建议您确认您的共享类型在客户端和服务器上完全相同。否则,您可能会遇到此问题。


11
投票

对于这个确切的问题,我一直在抨击我一整天。我刚修好了。这是如何做...

该服务必须通过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设置”下,确保选中“要求SSL”,并选中“客户端证书”单选按钮以“接受”。问题解决了!


9
投票

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


4
投票

我发现每当我添加引用,删除它,然后重新添加具有相同名称的服务时,这种情况就会发生。类型冲突似乎是由Visual Studio仍然可以看到的旧文件引起的。我需要做的就是修复它,在添加新引用之前是干净的。

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

希望这可以帮助。


3
投票

我从先前版本升级的Silverlight 5遇到了这个问题。

即使重新添加服务引用仍然给了我一个空的Reference.cs

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

我从来没有弄清楚问题到底是什么 - 但是.csproj文件中的某些内容未升级或某些设置出错。


1
投票

如果您最近在项目开始时向项目添加了一个集合,则问题可能是由两个具有相同CollectionDataContract属性的集合引起的:

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

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

我通过扫描我的项目并确保每个Name和ItemName属性都是唯一的来修复错误:

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

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

然后我刷新了服务参考,一切都恢复了。


1
投票

1
投票

在我阅读这些答案无济于事的情况下,对我来说有用的技术只是评论我的所有合同,并以二进制搜索方式取消注释,直到它不再起作用。这缩小了令人讨厌的代码。

然后你只需要猜出那段代码有什么问题。

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

我正在写一份网络服务合同。我有一个没有成员的占位符枚举。没关系。但是如果我在另一个类的属性中使用它,并在客户端上重用合约dll,则codegen会爆炸而没有错误消息。运行svcutil.exe没有帮助,它只是输出一个cs文件而没有提到原因。

© www.soinside.com 2019 - 2024. All rights reserved.