在VS 2015中生成服务引用时出错

时间:2016-04-01 04:17:34

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

好的,这在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

我的问题是代理生成器似乎无法看到DirectoryInfo名称空间中的System.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类。

1 个答案:

答案 0 :(得分:2)

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

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

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

有关详细信息,请参阅: