【发布时间】:2010-11-27 08:50:04
【问题描述】:
有时添加 WCF 服务引用会生成一个空的 reference.cs,我无法在项目中的任何位置引用该服务。
有人遇到过吗?
【问题讨论】:
有时添加 WCF 服务引用会生成一个空的 reference.cs,我无法在项目中的任何位置引用该服务。
有人遇到过吗?
【问题讨论】:
通常我发现这是一个代码生成问题,大部分是因为我遇到了无法解决的类型名称冲突。
如果您右键单击您的服务引用并单击配置并取消选中 “在引用的程序集中重用类型”,它可能会解决问题。
如果您使用此功能的某些方面,您可能需要确保您的姓名已被清理。
【讨论】:
正如公认的答案所指出的,重用类型时的类型引用问题可能是罪魁祸首。我发现当您无法轻松确定问题时,使用 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"
地点:
完整的 svcutil 命令行参考:http://msdn.microsoft.com/en-us/library/aa347733.aspx
运行 svcutil 后,您应该会看到导入引发的异常。您可能会收到关于您的一种类型的此类消息:“引用的类型无法使用,因为它与导入的 DataContract 不匹配”。
这可能只是指定的,因为引用程序集中的类型之一与在 DataContract 中为服务生成的类型不同。就我而言,我正在导入的服务具有来自共享程序集中的更新、更新的类型。这并不明显,因为异常中提到的类型似乎是相同的。不同的是该类型使用的嵌套复杂类型之一。
还有其他更复杂的场景可能会触发此类异常并导致空白reference.cs。 Here is one example.
如果您遇到此问题并且您没有在数据合同中使用泛型类型,也没有使用 IsReference = true,那么我建议您确认您的共享类型在客户端和服务器上完全相同。否则,您很可能会遇到此问题。
【讨论】:
发生这种情况时,请查看“错误”窗口和“输出”窗口以查看是否有任何错误消息。如果这没有帮助,请尝试手动运行 svcutil.exe,并查看是否有任何错误消息。
【讨论】:
我已经为这个确切的问题头疼了一整天。我刚刚修好了。方法如下...
服务必须通过 SSL 运行(即位于 https://mydomain.com/MyService.svc)
在开发服务器上添加对 WCF 服务的服务引用就可以了。
在实时生产服务器上部署 WCF 服务的精确相同版本,然后切换到客户端应用程序并将服务引用配置为指向实时服务显示没有错误,但应用程序不会t build:原来服务引用的 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”,然后选中“接受”的客户端证书单选按钮。问题已解决!
【讨论】:
我发现,每当我添加引用、删除它,然后重新添加同名服务时,都会经常出现这种情况。类型冲突似乎是由 Visual Studio 仍然可以看到的旧文件保留在某处引起的。我需要做的就是修复它,在添加新引用之前进行清理。
希望这会有所帮助。
【讨论】:
我在使用从以前版本升级的 Silverlight 5 时遇到了这个问题。
即使重新添加服务引用仍然给我一个空的 Reference.cs
我最终不得不创建一个全新的项目并重新创建服务参考。 如果您在这方面花费了大约半小时以上,则可以尝试一下。即使您决心修复原始项目,您也可能想尝试这样做只是为了看看会发生什么,然后再向后努力尝试解决问题。
我从来没有弄清楚到底是什么问题 - 但可能是 .csproj 文件中的某些内容未升级或某些设置出错。
【讨论】:
System.Xml.Linq - 如果你切换了版本,请检查所有 DLL 的版本
如果您最近在项目中添加了一个集合,而这开始发生,则问题可能是由具有相同 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> { }
然后我刷新了服务参考,一切都恢复了。
【讨论】:
【讨论】:
在我的案例中对我有用的技术,在阅读了这些答案无济于事之后,只是以二进制搜索方式注释掉我所有的合同,并取消注释位,直到它不再起作用。这缩小了有问题的代码。
那你只需要猜出那段代码有什么问题。
当然,该工具中的一些错误反馈会有所帮助。
我正在编写一份网络服务合同。我有一个没有成员的占位符枚举。没关系。但是,如果我在另一个类的属性中使用它,并在客户端上重新使用合同 dll,则代码生成会爆炸而没有错误消息。运行svcutil.exe也没有用,就是输出cs文件失败,不说原因。
【讨论】:
这里没有列出以下,这是我采用的解决方案(SvcUtils 在看到错误消息时很有用。但是,我得到的错误是wrapper type message cannot be projected as a data contract type since it has multiple namespaces。意思是,我遵循了这条线索,了解了@987654323 @ 来自this 帖子)。
就我而言,只需运行 wsdl [my-asmx-service-address] 即可生成一个没有问题的 .cs 文件,我将其包含在我的项目中并实例化以使用该服务。
【讨论】:
正如@dblood 指出的那样,主要的痛苦在于DataContractSerializer,它不能正确地重用类型。这里已经有了一些答案,所以我将首先添加一些关于这些的利弊:
幸运的是,如果您可以控制自己的服务,那么有一个简单的解决方案可以解决所有这些问题。这意味着您仍然可以跨 DLL 重用服务接口——这是 IMO 正确解决方案的必备条件。这就是解决方案的工作原理:
使用您喜欢的方法使用相同的 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 使用(正确的)服务类型。毕竟,你已经有了这些类。
专业人士:
缺点:
【讨论】:
在处理双方的项目引用(服务项目和具有服务引用的项目)时,我还遇到了服务引用损坏的问题。 例如,如果引用项目的 .dll 名为“Contoso.Development.Common”,但项目名称简称为“Common”,则对该项目的项目引用也仅命名为“Common”。但是,该服务需要引用“Contoso.Development.Common”来解析类(如果在服务引用选项中激活了此选项)。
因此,我使用资源管理器打开了引用服务和“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
【讨论】:
我昨天在开发过程中遇到了类似的问题。我发现我在 2 个不同版本的合同中使用了相同的命名空间。
我们有 2 个版本的合约,例如版本 4 和版本 5。我已经从版本 4 复制了所有合同,并将所有命名空间从版本 4 重命名为版本 5。在执行此操作时,我忘记在其中一个文件中将命名空间从 v4 重命名为 v5。由于命名空间冲突,Reference.cs 文件为空。
此问题很难解决,因为您在生成服务参考时不会收到任何错误消息。为了确定这个问题,我会手动验证我创建的所有新文件。还有其他方法可以解决这个问题。这是您在选择其他选项之前应该执行的第一步。
【讨论】:
感谢上面的 John Saunders 帖子,它给了我查看错误窗口的想法。我整天忙着脑袋,我正在查看输出窗口是否有任何错误。
在我的例子中,罪魁祸首是 ISerializable。我有一个具有异常类型的 DataMember 属性的 DataContract 类。您不能拥有任何具有 ISerializable 关键字的类型的 DataMember。在这个异常中,一旦我删除它,它就具有 ISerializable ,一切都像一个魅力。
【讨论】:
在尝试使用 svcutil 解决此问题时,我收到了 dblood 的答案中提到的错误(“引用类型无法使用,因为它与导入的 DataContract 不匹配”)。
在我的情况下,根本原因似乎是具有 DataContract 属性的枚举类型,但其成员未使用 EnumMember 属性进行标记。 svcutil 指向的问题类有一个具有该枚举类型的属性。
这更适合作为对 dblood 答案的评论,但没有足够的代表...
【讨论】:
在我的例子中,我有一个引用 C# UserControl 的 VB Web 窗体项目的解决方案。 VB 项目和 CS 项目都有对同一服务的服务引用。该引用出现在 VB 项目中的服务引用下和 CS(框架)项目中的连接服务分组下。
为了更新 VB Web 表单项目中的服务引用(即,让 Reference.vb 文件不为空),我需要删除 CS 项目,然后更新 VB 服务引用,然后添加 CS项目回到解决方案中。
【讨论】:
按照以下步骤操作:
添加服务时,这些文件夹中似乎有一些引用,导致自动生成代码时出错。
【讨论】: