ProtoBuff.NET WCF - Неправильная ошибка проводного типа на клиенте - PullRequest
0 голосов
/ 28 марта 2012

Мы используем 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 голосов
/ 05 апреля 2012

Что касается комментария Марка, в котором он заявил, что существуют способы заставить protobuf-net работать вместе с командой SvcUtil или «Add Service Reference» VS, я нашел этот пост, где он говорит:

Re Order = ..., стоило бы проверить содержимое;если они приходят с разными числами, есть способы исправить это с помощью частичного класса - безобразный хак, но в IIRC есть ProtoPartialMember (или аналогичный), который можно применить к классу, но который говорит об отдельном члене (свойстве/ поле).

Тогда есть этот пост, где он говорит:

Есть 2 варианта исправления этого;Первое (и самое простое) - использовать способность 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 {}
}
0 голосов
/ 28 марта 2012

Если вы не публикуете сборки контракта на обслуживание, как предложено в answer , то вам нужен способ заставить WCF использовать сериализатор ProtoBuf вместо сериализатора WCF по умолчанию в вашем клиентском коде.Проблема заключается в том, что маркировки атрибутов ProtoBuf в контракте на обслуживание не будут находиться в документе WSDL, который обычно используется для генерации прокси-сервера службы в коде клиента.

...