【问题标题】:Getting bad generated code from "Update Service Reference"从“更新服务参考”中获取错误的生成代码
【发布时间】:2009-08-18 14:30:35
【问题描述】:

在 VB.NET(使用 Visual Studio 2008)中,我的 WCF 服务有一个类似的接口:

<ServiceContract()> _
Public Interface IThingService
    <OperationContract()> _
    Function GetThingByNumber(ByVal thingNumber As MyKeyClass) As Thing
    <OperationContract()> _
    Function GetThing(ByVal thingId As Guid) As Thing

    ' ...

End Interface

我最近更改了两个具有相似代码的项目,以使用 basicHttpBinding 而不是 wsHttpBinding。一切都在服务端编译得很好。现在,在客户端应用程序中,我选择“更新服务参考”。在一个项目中,我生成的 reference.vb 似乎是正确的——不到 100 行,每种方法都有简单的包装器。但是,另一方面,生成的 reference.vb 似乎无法理解服务是什么。我得到一个超过 1000 行的 reference.vb,如下所示:

 '------------------------------------------------------------------------------
 ' <auto-generated>
 '     This code was generated by a tool.
 '     Runtime Version:2.0.50727.3053
 '
 '     Changes to this file may cause incorrect behavior and will be lost if
 '     the code is regenerated.
 ' </auto-generated>
 '------------------------------------------------------------------------------
 Option Strict On
 Option Explicit On
 Imports System.Data
 Namespace ThingService

 <System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0"),  _
 System.ServiceModel.ServiceContractAttribute(ConfigurationName:="GetThingByVersion.IGetThingByVersion")>  _
 Public Interface IThingService

    'CODEGEN: Parameter 'GetThingByNumberResult' requires additional schema information that cannot be captured using the parameter mode. The specific attribute is 'System.Xml.Serialization.XmlElementAttribute'.
    <System.ServiceModel.OperationContractAttribute(Action:="http://tempuri.org/ThingService/GetThingByVersion", ReplyAction:="http://tempuri.org/ hingService/GetThingByVersionResponse"),  _
     System.ServiceModel.XmlSerializerFormatAttribute()>  _
    Function GetThingByNumber(ByVal request As ThingService.GetThingByVersionRequest) As ThingService.GetThingByVersionResponse

    'CODEGEN: Parameter 'GetThingResult' requires additional schema information that cannot be captured using the parameter mode. The specific attribute is 'System.Xml.Serialization.XmlElementAttribute'.
    <System.ServiceModel.OperationContractAttribute(Action:="http://tempuri.org/ThingService/GetThing", ReplyAction:="http://tempuri.org/ThingService/GetThingResponse"),  _
     System.ServiceModel.XmlSerializerFormatAttribute()>  _
    Function GetThing(ByVal request As ThingService.GetThingRequest) As ThingService.GetThingResponse
'...
End Interface

 '''<remarks/>
 <System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3082"),  _
 System.SerializableAttribute(),  _
 System.Diagnostics.DebuggerStepThroughAttribute(),  _
 System.ComponentModel.DesignerCategoryAttribute("code"),  _
 System.Xml.Serialization.XmlTypeAttribute([Namespace]:="http://schemas.datacontract.org/2004/07/ThingLibraryCore")>  _
 Partial Public Class MyKeyClass
    Inherits Object
    Implements System.ComponentModel.INotifyPropertyChanged

    Private concatenatedThingNumberField As String
    Private ThingNumberField As Integer
    Private ThingNumberFieldSpecified As Boolean

 '... goes on and on...

好像生成的代码对我的实际服务接口一无所知。知道如何解决这个问题吗?提前致谢。

编辑:看起来我需要确保服务器可以使用 DataContractSerializer 而不是 XmlSerializer:请参阅 http://blogs.msdn.com/sonuarora/archive/2007/06/16/contract-generation-from-wsdl-xml-schema-datacontractserializer-vs-xmlserializer.aspx 。有谁知道我如何弄清楚我的代码(可能在 Class Thing 中)违反了 DataContractSerializer 的限制?

【问题讨论】:

  • 查看生成代码中的cmets。他们在告诉你出了什么问题。
  • 我听不懂。什么是“参数模式”?它应该在哪里获取模式信息? XmlElementAttribute 应该告诉我什么?我在谷歌上搜索无济于事。
  • 注意,例如GetThing(Guid)在接口中,但是生成的客户端有GetThing(String)。我也想不出那部分。
  • 有谁知道我如何弄清楚我的代码(可能在 Class Thing 中)违反了 DataContractSerializer 的限制?
  • 我是对的:Thing 中有一个属性是 DataContractSerializer 无法处理的,因此它回退到使用 XmlSerializer,这会生成不可用的架构/客户端代码。有问题的属性继承自通用 Dictionary(Of string, OtherClass)。我会使用 KnownTypeAttribute 来克服这个问题,但我不能,因为它的属性似乎不适用于泛型。我将为 Dictionary(Of string, OtherClass) 创建一个包装器,而不是从它继承。

标签: .net visual-studio wcf xml-serialization datacontractserializer


【解决方案1】:

老实说,我不确定答案是什么。您是否尝试过删除服务引用并从头开始重新创建它?这似乎是尝试修复它的最直接的方法,尤其是在您进行了更改之后。

我知道你没有问这个问题,但顺便说一句,我个人完全放弃了在 Visual Studio 中使用服务引用功能。这是一个很好的video,它描述了它是多么容易,只要你愿意稍微重构你的代码。由于听起来您同时负责 WCF 客户端和服务器,我认为您将从 Miguel 倡导的方法中受益匪浅。

编辑:

针对 John Saunder 的评论,如果您同时负责客户端和服务器,那么在我看来,您最好将合同(服务和数据合同)重新分解为一个程序集在客户端和服务器之间共享。当您添加/更新服务引用时,所做的只是为客户端生成这些合同的代码生成副本,然后为代理添加样板代码。所以本质上,这些接口和类有两个独立但相同的定义,一个在服务器端,一个在客户端。

我从这样做迁移的原因是因为我在 Windows 服务中托管了 WCF 服务。在我的整个项目中,客户在四个单独的程序集中使用了此服务。每次对 WCF 服务的服务/数据合同进行更改时,我都必须更新使用 WCF 服务的四个程序集中的服务引用。通过将这些合同重构为单个共享程序集,我更新了该程序集,重新编译(无论如何我都必须这样做),然后我就可以开始了。我不再需要记住哪些程序集需要更新。

我意识到网络上的许多示例都在谈论使用 svcutil 工具的简单性,但就我而言,这是不必要的开销。

观看视频并自行判断。

【讨论】:

  • 我建议不要这样做,没有更好的理由。您在网络上找到的几乎所有示例都将使用服务引用。
  • 添加服务引用允许您使用来自共享程序集的类型。只需点击“高级”按钮。
  • 谢谢,马特——那个视频很有帮助。即使我做了“简单”的手动客户端创建(使用 ChannelFactory 方法),我认为我们在处理 Dictionary(Of string, TVal) 时会遇到序列化方式的问题。我打算从简单开始。
  • @John Saunders,我会检查一下。但即便如此,当界面更改时,我仍然必须在“使用”服务的每个位置更新客户端代理。将所有内容重新分解为一个程序集可以让我绕过这个头痛。
  • 视频不错。我现在还建议在服务合同发生变化时在任何可以发布新 DLL 的地方避免使用服务引用。
【解决方案2】:

确保您的所有数据合约仅包含返回类型为原始数据类型或任何其他 dataContact 的属性。需要 XMLSerialization 的 DataSet 和 DataType 等数据类型会将您的数据合同转换为 MessegeContract,代码生成器只会显示与注释相同的消息。

【讨论】:

    猜你喜欢
    • 2015-01-29
    • 2013-03-08
    • 1970-01-01
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多