ProtoBuff.NET WCF - 客户端上的线路类型错误

时间:2012-03-28 02:40:08

标签: wcf protobuf-net nettcpbinding

我们正在使用ProtoBuff.NET和我们的WCF服务。 ProtoBehavour已应用于界面,ProtoContract已应用于该类& ProtoMember已应用于这些属性。

在客户端,我们已将protobuff行为添加到app.config,如下所示,但是当客户端通过WCF服务请求对象时,我们收到错误的线路类型错误。

删除服务上的ProtoBuff行为会导致服务正常工作。

任何人都可以了解正在发生的事情或指出我们正确的方向。

我们正在使用NET TCP绑定。

客户端配置

<behaviors>
        <endpointBehaviors>
            <behavior name="ProtoBufBehaviorConfig">
                <ProtoBufSerialization/>
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <extensions>
        <behaviorExtensions>
            <add name="ProtoBufSerialization" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.480, Culture=neutral, PublicKeyToken=257b51d87d2e4d67"/>
        </behaviorExtensions>
    </extensions>

示例类

<DataContract()> <ProtoBuf.ProtoContract()> _
Public Class Product
    Private _ID As String
    <DataMember(Order:=1)> <ProtoBuf.ProtoMember(1)> _
    Public Property ID As String
        Get
            Return _ID
        End Get
        Set(value As String)
            _ID = value
        End Set
    End Property

    Private _Name As String
    <DataMember(Order:=2)> <ProtoBuf.ProtoMember(2)> _
    Public Property Name As String
        Get
            Return _Name
        End Get
        Set(value As String)
            _Name = value
        End Set
    End Property

    Private _Supplier As Supplier
    <DataMember(Order:=3)> <ProtoBuf.ProtoMember(3)> _
    Public Property Supplier As Supplier
        Get
            Return _Supplier
        End Get
        Set(value As Supplier)
            _Supplier = value
        End Set
    End Property

    Private _Income_Group As Primary_Income_Group
    <DataMember(Order:=4)> <ProtoBuf.ProtoMember(4)> _
    Public Property Primary_Income_Group As Primary_Income_Group
        Get
            Return _Income_Group
        End Get
        Set(value As Primary_Income_Group)
            _Income_Group = value
        End Set
    End Property

    Private _Margin_Percentage As Decimal
    <DataMember(Order:=5)> <ProtoBuf.ProtoMember(5)> _
    Public Property Margin_Percentage As Decimal
        Get
            Return _Margin_Percentage
        End Get
        Set(value As Decimal)
            _Margin_Percentage = value
        End Set
    End Property

    Private _Cost_Price_exGST As Decimal
    <DataMember(Order:=6)> <ProtoBuf.ProtoMember(6)> _
    Public Property Cost_Price_exGST As Decimal
        Get
            Return _Cost_Price_exGST
        End Get
        Set(value As Decimal)
            _Cost_Price_exGST = value
        End Set
    End Property

    Private _Retail_Price_incGST As Decimal
    <DataMember(Order:=7)> <ProtoBuf.ProtoMember(7)> _
    Public Property Retail_Price_incGST As Decimal
        Get
            Return _Retail_Price_incGST
        End Get
        Set(value As Decimal)
            _Retail_Price_incGST = value
        End Set
    End Property

    Private _Active As Boolean
    <DataMember(Order:=8)> <ProtoBuf.ProtoMember(8)> _
    Public Property Active As Boolean
        Get
            Return _Active
        End Get
        Set(value As Boolean)
            _Active = value
        End Set
    End Property

    Private _Image As String
    <DataMember(Order:=9)> <ProtoBuf.ProtoMember(9)> _
    Public Property Image As String
        Get
            Return _Image
        End Get
        Set(value As String)
            _Image = value
        End Set
    End Property

    Private _Secondary_Income_Group As Secondary_Income_Group
    <DataMember(Order:=10)> <ProtoBuf.ProtoMember(10)> _
    Public Property Secondary_Income_Group As Secondary_Income_Group
        Get
            Return _Secondary_Income_Group
        End Get
        Set(value As Secondary_Income_Group)
            _Secondary_Income_Group = value
        End Set
    End Property
End Class

服务器配置摘录

Dim TCPBinding As NetTcpBinding = New NetTcpBinding With { _
              .PortSharingEnabled = True, _
              .ListenBacklog = 5000, _
              .ReaderQuotas = New System.Xml.XmlDictionaryReaderQuotas With {.MaxArrayLength = Integer.MaxValue, .MaxBytesPerRead = Integer.MaxValue, .MaxDepth = Integer.MaxValue, .MaxNameTableCharCount = Integer.MaxValue, .MaxStringContentLength = Integer.MaxValue}, _
              .MaxConnections = 10000, _
              .TransferMode = TransferMode.Buffered, _
              .MaxBufferSize = Integer.MaxValue, _
              .MaxReceivedMessageSize = Integer.MaxValue, _
              .ReliableSession = New System.ServiceModel.OptionalReliableSession With {.Enabled = False}, _
              .Security = New System.ServiceModel.NetTcpSecurity With { _
                                                       .Mode = SecurityMode.Transport, _
                                                       .Transport = New System.ServiceModel.TcpTransportSecurity With {.ProtectionLevel = Net.Security.ProtectionLevel.Sign, .ClientCredentialType = TcpClientCredentialType.Windows} _
                                                   } _
          }
.....
Dim endpoint As ServiceEndpoint = ServiceHostObject.AddServiceEndpoint(Contract, TCPBinding, "")
endpoint(New ProtoBuf.ServiceModel.ProtoEndpointBehavior)

2 个答案:

答案 0 :(得分:0)

如果您没有按照marc answer中的建议共享服务合同程序集,那么您需要一种方法让WCF在您的客户端代码中使用ProtoBuf序列化程序而不是WCF默认序列化程序。问题是服务契约中的ProtoBuf属性标记不会位于通常用于在客户端代码中生成服务代理的WSDL文档中。

答案 1 :(得分:0)

关于Marc的评论,他说有很多方法可以与SvcUtil或“添加服务参考”VS命令一起进行protobuf-net工作,我找到this帖子,他说:

  

重新订单= ......,值得查看内容;如果他们提出不同的数字,有办法通过部分类来解决这个问题 - 一个丑陋的黑客,但IIRC有ProtoPartialMember(或类似的)可以应用于类,但谈论个别成员(属性) /领域)。

然后有this帖子,他说:

  

有两种方法可以解决这个问题;第一个(也是最简单的)是使用WCF在客户端和服务器之间共享合同程序集的能力。如果您可以共享DTO图层,那么事情就会变得简单。

     

第二种是在客户端添加额外的标记以给它一个线索。您可以通过部分类来完成此操作,例如在单独的代码文件中(不要编辑生成的文件):

namespace YourNamespace {
    [ProtoContract(DataMemberOffset = 1)] /* shift all DataMember orders */
    public partial class tbEmployee {}
}
  

更明确的替代方案是:

namespace YourNamespace {
    [ProtoPartialMember(1, "EmployeeID")]
    [ProtoPartialMember(2, "EmployeeName")]
    public partial class tbEmployee {}
}