【问题标题】:Sometimes adding a WCF Service Reference generates an empty reference.cs有时添加 WCF 服务引用会生成一个空的 reference.cs
【发布时间】:2010-11-27 08:50:04
【问题描述】:

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

有人遇到过吗?

【问题讨论】:

    标签: c# .net wcf


    【解决方案1】:

    通常我发现这是一个代码生成问题,大部分是因为我遇到了无法解决的类型名称冲突。

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

    如果您使用此功能的某些方面,您可能需要确保您的姓名已被清理。

    【讨论】:

    • 当它发生在我身上时,我发现我还需要将 Collection Type 从 ObjectModel.ObservableCollection 更改为 Generic.List
    • 发生在我身上是因为我添加到部分类中。
    • 但是,如果您想使用特定程序集中的类型,您可以只选择该程序集,它也可以正常工作(至少在我的情况下),ta
    • 令人难以置信的是,即使在 6 年后,我每周平均从这个问题中获得 50 分。来吧,MS,解决这个问题。至少在效果不佳时给开发人员一些反馈,而不是让他们盯着空白文件。
    • 9 年后,您仍在提供帮助。谢谢!
    【解决方案2】:

    正如公认的答案所指出的,重用类型时的类型引用问题可能是罪魁祸首。我发现当您无法轻松确定问题时,使用 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 后,您应该会看到导入引发的异常。您可能会收到关于您的一种类型的此类消息:“引用的类型无法使用,因为它与导入的 DataContract 不匹配”。

    这可能只是指定的,因为引用程序集中的类型之一与在 DataContract 中为服务生成的类型不同。就我而言,我正在导入的服务具有来自共享程序集中的更新、更新的类型。这并不明显,因为异常中提到的类型似乎是相同的。不同的是该类型使用的嵌套复杂类型之一。

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

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

    【讨论】:

    • 就我而言,这是在我引用了一个也引用了我的 WCF 服务的程序集之后发生的。从程序集列表中删除该程序集以与固定它共享类型。
    • 我在添加服务引用时收到一条毫无意义的错误消息(只是一个命名空间),这指出了问题。
    【解决方案3】:

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

    【讨论】:

    • @svcutil.exe如何运行?你能帮帮我吗?
    • @Arul:使用 Google 查找有关 svcutil.exe 的信息。
    • 不确定微软是否已经阅读了这篇文章,但即使只是显示一个消息框来说明错误和警告,而不是只是默默地将它们放在(最小化,在我的情况下)错误列表窗口中所以我不需要谷歌这个。或者,我想当有新的警告/错误时,让标签显示为红色或黄色会很有用?
    【解决方案4】:

    我已经为这个确切的问题头疼了一整天。我刚刚修好了。方法如下...

    服务必须通过 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”,然后选中“接受”的客户端证书单选按钮。问题已解决!

    【讨论】:

      【解决方案5】:

      我发现,每当我添加引用、删除它,然后重新添加同名服务时,都会经常出现这种情况。类型冲突似乎是由 Visual Studio 仍然可以看到的旧文件保留在某处引起的。我需要做的就是修复它,在添加新引用之前进行清理。

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

      希望这会有所帮助。

      【讨论】:

      • 这个是为我做的,其他解决方案导致一个空的 Reference.cs
      【解决方案6】:

      我在使用从以前版本升级的 Silverlight 5 时遇到了这个问题。

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

      我最终不得不创建一个全新的项目并重新创建服务参考。 如果您在这方面花费了大约半小时以上,则可以尝试一下。即使您决心修复原始项目,您也可能想尝试这样做只是为了看看会发生什么,然后再向后努力尝试解决问题。

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

      【讨论】:

      • 好吧,原来我引用的是旧版本的 System.Xml.Linq - 如果你切换了版本,请检查所有 DLL 的版本
      【解决方案7】:

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

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

      我通过扫描我的项目并确保每个 NameItemName 属性都是唯一的,从而修复了该错误:

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

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

      【讨论】:

        【解决方案8】:

        【讨论】:

        • 这很明显,但很容易被忽视或认为不重要。
        【解决方案9】:

        在我的案例中对我有用的技术,在阅读了这些答案无济于事之后,只是以二进制搜索方式注释掉我所有的合同,并取消注释位,直到它不再起作用。这缩小了有问题的代码。

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

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

        我正在编写一份网络服务合同。我有一个没有成员的占位符枚举。没关系。但是,如果我在另一个类的属性中使用它,并在客户端上重新使用合同 dll,则代码生成会爆炸而没有错误消息。运行svcutil.exe也没有用,就是输出cs文件失败,不说原因。

        【讨论】:

        • 注释掉所有对我有用的操作合同。我认为错误的方法是罪魁祸首。感谢您提供回归基础的故障排除方法。
        【解决方案10】:

        这里没有列出以下,这是我采用的解决方案(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 文件,我将其包含在我的项目中并实例化以使用该服务。

        【讨论】:

          【解决方案11】:

          正如@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 使用(正确的)服务类型。毕竟,你已经有了这些类。

          专业人士:

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

          缺点:

          1. 异步方法很麻烦,因为您不生成异步代理。因此,我不建议在 Silverlight 应用程序中这样做。

          【讨论】:

            【解决方案12】:

            在处理双方的项目引用(服务项目和具有服务引用的项目)时,我还遇到了服务引用损坏的问题。 例如,如果引用项目的 .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

            【讨论】:

              【解决方案13】:

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

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

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

              【讨论】:

                【解决方案14】:

                感谢上面的 John Saunders 帖子,它给了我查看错误窗口的想法。我整天忙着脑袋,我正在查看输出窗口是否有任何错误。

                在我的例子中,罪魁祸首是 ISerializable。我有一个具有异常类型的 DataMember 属性的 DataContract 类。您不能拥有任何具有 ISerializable 关键字的类型的 DataMember。在这个异常中,一旦我删除它,它就具有 ISerializable ,一切都像一个魅力。

                【讨论】:

                  【解决方案15】:

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

                  在我的情况下,根本原因似乎是具有 DataContract 属性的枚举类型,但其成员未使用 EnumMember 属性进行标记。 svcutil 指向的问题类有一个具有该枚举类型的属性。

                  这更适合作为对 dblood 答案的评论,但没有足够的代表...

                  【讨论】:

                    【解决方案16】:

                    在我的例子中,我有一个引用 C# UserControl 的 VB Web 窗体项目的解决方案。 VB 项目和 CS 项目都有对同一服务的服务引用。该引用出现在 VB 项目中的服务引用下和 CS(框架)项目中的连接服务分组下。

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

                    【讨论】:

                      【解决方案17】:

                      按照以下步骤操作:

                      1. 删除服务参考
                      2. 关闭 Visual Studio
                      3. 删除 /Bin 和 /Obj 文件夹。
                      4. 打开 Visual Studio。
                      5. 添加服务参考。
                      6. 不客气 :)

                      添加服务时,这些文件夹中似乎有一些引用,导致自动生成代码时出错。

                      【讨论】:

                        猜你喜欢
                        • 2013-04-13
                        • 2012-03-02
                        • 2014-03-22
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-03-21
                        • 2013-05-17
                        • 2017-08-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多