【问题标题】:Error generating service reference in VS 2015在 VS 2015 中生成服务参考时出错
【发布时间】:2016-04-01 04:17:33
【问题描述】:

好的,这在 VS 2013 中工作得很好。只有当我升级到 2015 后重新开始该项目时,问题才出现。

简而言之,我不确定如何告诉 WCF 代理生成器为属性类型指定 CLR 命名空间;显然这是现在需要的。

这是我的合同:

<ServiceContract>
Friend Interface IService
  <OperationContract> Function CheckFiles() As List(Of String)
  <OperationContract> Function CreateBackup(AllFiles As List(Of String)) As BackupResult
End Interface

这是返回的类:

Public Class BackupResult
  Public Property DbService As New DbService
  Public Property TmpFolder As System.IO.DirectoryInfo ' <== Problem here '
  Public Property Chunks As Integer
End Class

为了清楚起见,这里是 DbService 属性的类(尽管它与这个问题的唯一相关性是表明它没有任何 System.IO 引用)。

Public Class DbService
  Public Property ErrorMessage As String = String.Empty
  Public Property HasError As Boolean = False
End Class

我的问题是代理生成器似乎无法看到DirectoryInfoSystem.IO 命名空间中——它一直在服务的命名空间中生成它。 (当我注释掉 CreateBackup() 函数,重新运行服务并更新引用时,不会生成 QbBackup.DirectoryInfo 类。我没有收到下面显示的警告,并且一切正常——就像 2013 年一样——但是当然没有我需要的财产。)

这是生成的代码:

Namespace QbServer

  ' ...                                          '
  '                                              '
  ' Other generated code here                    '
  '                                              '
  ' ...                                          '
  '                                              '
  ' Note the generated DirectoryInfo class and   '
  ' the BackupResult.TmpFolder property of type  '
  ' QbServer.DirectoryInfo, when the namespace   '
  ' should be System.IO instead                  '
  '                                              '

  <System.Diagnostics.DebuggerStepThroughAttribute(),
     System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0"),
     System.Runtime.Serialization.DataContractAttribute(Name:="BackupResult", [Namespace]:="http://schemas.datacontract.org/2004/07/Service"),
     System.SerializableAttribute()>
  Partial Public Class BackupResult
    Inherits Object
    Implements System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged

    <System.NonSerializedAttribute()>
    Private extensionDataField As System.Runtime.Serialization.ExtensionDataObject

    <System.Runtime.Serialization.OptionalFieldAttribute()>
    Private ChunksField As Integer

    <System.Runtime.Serialization.OptionalFieldAttribute()>
    Private DbServiceField As QbServer.DbService

    <System.Runtime.Serialization.OptionalFieldAttribute()>
    Private TmpFolderField As QbServer.DirectoryInfo

    <Global.System.ComponentModel.BrowsableAttribute(False)>
    Public Property ExtensionData() As System.Runtime.Serialization.ExtensionDataObject Implements System.Runtime.Serialization.IExtensibleDataObject.ExtensionData
      Get
        Return Me.extensionDataField
      End Get
      Set
        Me.extensionDataField = Value
      End Set
    End Property

    <System.Runtime.Serialization.DataMemberAttribute()>
    Public Property Chunks() As Integer
      Get
        Return Me.ChunksField
      End Get
      Set
        If (Me.ChunksField.Equals(Value) <> True) Then
          Me.ChunksField = Value
          Me.RaisePropertyChanged("Chunks")
        End If
      End Set
    End Property

    <System.Runtime.Serialization.DataMemberAttribute()>
    Public Property DbService() As QbServer.DbService
      Get
        Return Me.DbServiceField
      End Get
      Set
        If (Object.ReferenceEquals(Me.DbServiceField, Value) <> True) Then
          Me.DbServiceField = Value
          Me.RaisePropertyChanged("DbService")
        End If
      End Set
    End Property

    <System.Runtime.Serialization.DataMemberAttribute()>
    Public Property TmpFolder() As QbServer.DirectoryInfo
      Get
        Return Me.TmpFolderField
      End Get
      Set
        If (Object.ReferenceEquals(Me.TmpFolderField, Value) <> True) Then
          Me.TmpFolderField = Value
          Me.RaisePropertyChanged("TmpFolder")
        End If
      End Set
    End Property

    Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    Protected Sub RaisePropertyChanged(ByVal propertyName As String)
      Dim propertyChanged As System.ComponentModel.PropertyChangedEventHandler = Me.PropertyChangedEvent
      If (Not (propertyChanged) Is Nothing) Then
        propertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName))
      End If
    End Sub
  End Class

  <System.Diagnostics.DebuggerStepThroughAttribute(),
     System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")>
  Public Class DirectoryInfo
  End Class
End Namespace

这是我在 Visual Studio 2015 中收到的警告:

自定义工具警告:无法导入 wsdl:portType 详细信息:运行 WSDL 导入扩展时引发异常:System.ServiceModel.Description.DataContractSerializerMessageContractImporter 错误:无法导入命名空间“http://schemas.datacontract.org/2004/07/System.IO”中数据协定名称为“DirectoryInfo”的 ISerializable 类型。无法为 ISerializable 类型自定义数据协定命名空间,并且生成的命名空间“QbServer”与所需的 CLR 命名空间“System.IO”不匹配。检查所需的命名空间是否已映射到不同的数据协定命名空间,并考虑使用命名空间集合显式映射它。 错误源的 XPath://wsdl:definitions[@targetNamespace='http://tempuri.org/']/wsdl:portType[@name='IService'] ConsoleTest D:\Dev\Customers\OIT\Active\ConsoleTest\Service References\QbServer \Reference.svcmap 1

这一切都会导致代理类没有被生成。

我一直在阅读thisthis,但它们似乎与服务级别的自定义命名空间有关。我需要知道如何告诉生成器将属性类型识别为 CLR 类型,而不是生成自己的 DirectoryInfo 类。

【问题讨论】:

  • 问题在于您使用的是DataContractSerializer,它不支持ISerializable 字段。只有原语和其他数据契约。您将需要改用 XmlSerializer 并处理增加的复杂性,或者将字段的类型改为字符串(这很有意义,不是吗)。
  • @jessehouwing:我在使用XmlSerializerFormat 时遇到了更多的问题,所以我最终只使用了一个字符串,一端解构,另一端重构。所以感谢您的参与——我将来会警惕 WCF 和 System.IO。为什么不把它作为一个答案,以便我可以标记它? (顺便说一句,你最喜欢的 Scrum 论坛是什么?)

标签: wcf visual-studio-2013 visual-studio-2015


【解决方案1】:

DataContractSerializer 不支持 System.IO.DirectoryInfo 类。相反,您可以尝试使用 XmlSerializer,但您可能会遇到其他问题。

一个简单的解决方案是添加一个string 属性,该属性捕获重新创建正确对象所需的数据。您也可以保留原始属性,但请务必使用 [NonSerialized] 属性对其进行标记。

或者,您可以使用OnSerializingOnDeserializing 属性确保DirectoryInfo 值存储在字符串字段中,以便在反序列化后恢复DirectoryInfo。

欲了解更多信息,请参阅:

【讨论】:

  • 知道了,谢谢。这些回调很有趣——我会进一步调查。
  • 具体来说,我遇到了XmlSerializerDirectoryInfo 缺少无参数构造函数的问题。您引用的博客文章很好地讨论了为什么DirectoryInfoDataContractSerializer 一起使用而不是XmlSerializer。这是一篇非常好的文章。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-26
  • 1970-01-01
  • 1970-01-01
  • 2015-11-15
相关资源
最近更新 更多