从“更新服务参考”获取错误的生成代码
在 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 的限制?
In VB.NET (using Visual Studio 2008) my WCF service has an interface something like:
<ServiceContract()> _
Public Interface IThingService
<OperationContract()> _
Function GetThingByNumber(ByVal thingNumber As MyKeyClass) As Thing
<OperationContract()> _
Function GetThing(ByVal thingId As Guid) As Thing
' ...
End Interface
I recently changed two projects with similar code to use a basicHttpBinding rather than a wsHttpBinding. Everything compiles well on the service side. Now, in the a client app I choose "Update Service Reference". In one project, my resulting reference.vb seems correct--under 100 lines with simple wrappers for each method. However, in the other, the resulting reference.vb can't seem to understand what the service is. I get a reference.vb of over 1000 lines that looks like:
'------------------------------------------------------------------------------
' <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...
It's as if the code generated knows nothing of my actual service interface. Any idea how to troubleshoot this? Thanks in advance.
EDIT: Looks like I need to make sure that the server can use the DataContractSerializer and not the XmlSerializer: see http://blogs.msdn.com/sonuarora/archive/2007/06/16/contract-generation-from-wsdl-xml-schema-datacontractserializer-vs-xmlserializer.aspx . Does anyone know how I can figure out what in my code (probably in Class Thing) is violating the restrictions on DataContractSerializer?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
老实说,我不确定答案是什么。 您是否尝试过删除服务引用并从头开始重新创建它? 这似乎是尝试修复它的最直接的方法,特别是因为您已经做出了更改。
我知道你没有问这个,但顺便说一句,我个人已经完全放弃使用 Visual Studio 中的服务引用功能。 这是一个很棒的视频,它描述了它是多么容易做到,为您提供愿意稍微重构你的代码。 由于听起来您同时负责 WCF 客户端和服务器,因此我认为您将从 Miguel 倡导的方法中受益匪浅。
编辑:
为了回应 John Saunder 的评论,如果您同时负责客户端和服务器,在我看来,您最好将合同(服务和数据合同)重构为单个程序集在客户端和服务器之间共享。 当您添加/更新服务引用时,所做的就是为客户端制作这些合约的代码生成副本,然后添加代理的样板代码。 因此,本质上,这些接口和类有两个独立但相同的定义,一个在服务器端,一个在客户端。
我不再这样做的原因是因为我有一个托管在 Windows 服务中的 WCF 服务。 在我的项目中,客户在四个独立的程序集中使用了该服务。 每次更改 WCF 服务的服务/数据协定时,我都必须更新使用 WCF 服务的四个程序集中的服务引用。 通过将这些合同重构为单个共享程序集,我更新该程序集,重新编译(无论如何我都必须这样做),然后就可以开始了。 我不再需要记住哪些程序集需要更新。
我意识到网络上的许多示例都谈论使用 svcutil 工具的简单性,但就我而言,这是不必要的开销。
观看视频并自行判断。
Honestly, I'm not sure what the answer is. Have you tried deleting the service reference and re-creating it from scratch? That would seem to be the most straightforward way to try to fix it, especially since you've made changes.
I know you didn't ask this, but as an aside, I have personally gotten away from using the service reference feature in visual studio altogether. Here is an excellent video that describes how easy it is to do, providing you are willing to refactor your code a little bit. Since it sounds like you are in charge of both WCF client and server, I think you'd benefit tremendously from the approach Miguel advocates.
EDIT:
In response to John Saunder's comment, if you are in charge of both the client and the server, you'd be better off, in my opinion, to re-factor the contracts (service and data contracts) into a single assembly that is shared between the client and server. When you add/update a service reference, all that does is make a code-generated copy of these contracts for the client and then adds the boilerplate code for the proxy. So in essence, you have two separate, but identical, definitions of these interfaces and classes, one on the server side and one on the client side.
The reason I migrated from doing this is because I have a WCF service hosted in a Windows service. This service was used by clients in four separate assemblies throughout my project. Every time I made a change to the service/data contract for the WCF service, I had to go update the service reference in the four assemblies that used the WCF service. By refactoring these contracts to a single, shared assembly, I update that assembly, re-compile (which I would have to do anyway), and I'm ready to go. I no longer have to remember which assemblies need to be updated.
I realize that many of the examples on the web talk about the simplicity of using the svcutil tool, but in my case, it's unnecessary overhead.
Take a look at the video and judge for yourself.
确保所有数据契约仅包含返回类型为原始数据类型或任何其他 dataContact 的属性。 需要 XMLSerialization 的数据类型(例如 DataSet 和 DataType)会将您的数据契约转换为 MessegeContract,并且代码生成器仅显示与注释相同的消息。
Make sure all your datacontract contains only those properties which has return type as either primitive data type or any other dataContact. Datatype such as DataSet and DataType which requires XMLSerialization will convert your datacontract to MessegeContract and code generator simply displays the same messege as comment.