ProtoBuff.NET WCF - 客户端上的线类型错误不正确 [英] ProtoBuff.NET WCF - Incorrect wire-type error on client

查看:44
本文介绍了ProtoBuff.NET WCF - 客户端上的线类型错误不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在 WCF 服务中使用 ProtoBuff.NET.ProtoBehavour 已应用于接口,ProtoContract 已应用于类 &ProtoMember 已应用于属性.

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

删除服务上的 ProtoBuff 行为会导致服务正常运行.

任何人都可以对正在发生的事情有所了解或为我们指明正确的方向.

我们使用的是 NET TCP 绑定.

客户端配置

<端点行为><行为名称="ProtoBufBehaviorConfig"><ProtoBufSerialization/></行为></endpointBehaviors></行为><扩展><行为扩展><add name="ProtoBufSerialization" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=2.0.0.480, Culture=neutral, PublicKeyToken=257b51d87d2e4d67"/></behaviorExtensions></扩展名>

示例类

<ProtoBuf.ProtoContract()>_公共类产品私有 _ID 作为字符串<DataMember(Order:=1)><ProtoBuf.ProtoMember(1)>_公共属性 ID 作为字符串得到返回_ID结束获取设置(值作为字符串)_ID = 值结束集最终财产私有 _Name 作为字符串<DataMember(Order:=2)><ProtoBuf.ProtoMember(2)>_公共属性名称作为字符串得到返回_名称结束获取设置(值作为字符串)_名称 = 值结束集最终财产Private _Supplier 作为供应商<DataMember(Order:=3)><ProtoBuf.ProtoMember(3)>_公共财产供应商作为供应商得到退货_供应商结束获取设置(值作为供应商)_供应商=价值结束集最终财产Private _Income_Group 作为 Primary_Income_Group<DataMember(Order:=4)><ProtoBuf.ProtoMember(4)>_公共财产 Primary_Income_Group 作为 Primary_Income_Group得到返回_收入_组结束获取设置(值作为 Primary_Income_Group)_Income_Group = 价值结束集最终财产Private _Margin_Percentage 为十进制<DataMember(Order:=5)><ProtoBuf.ProtoMember(5)>_公共财产 Margin_Percentage 为十进制得到回报_Margin_Percentage结束获取设置(值为十进制)_Margin_Percentage = 值结束集最终财产Private _Cost_Price_exGST 作为十进制<DataMember(Order:=6)><ProtoBuf.ProtoMember(6)>_公共财产 Cost_Price_exGST 作为十进制得到返回_Cost_Price_exGST结束获取设置(值为十进制)_Cost_Price_exGST = 价值结束集最终财产Private _Retail_Price_incGST 作为十进制<DataMember(Order:=7)><ProtoBuf.ProtoMember(7)>_Public Property Retail_Price_incGST 作为十进制得到返回_Retail_Price_incGST结束获取设置(值为十进制)_Retail_Price_incGST = 价值结束集最终财产Private _Active 作为布尔值<DataMember(Order:=8)><ProtoBuf.ProtoMember(8)>_公共属性激活为布尔值得到返回_Active结束获取设置(值作为布尔值)_Active = 值结束集最终财产私有 _Image 作为字符串<DataMember(Order:=9)><ProtoBuf.ProtoMember(9)>_公共属性图像作为字符串得到返回_Image结束获取设置(值作为字符串)_图像 = 值结束集最终财产Private _Secondary_Income_Group 作为 Secondary_Income_Group<DataMember(Order:=10)><ProtoBuf.ProtoMember(10)>_公共财产 Secondary_Income_Group 作为 Secondary_Income_Group得到返回_Secondary_Income_Group结束获取设置(值作为 Secondary_Income_Group)_Secondary_Income_Group = 价值结束集最终财产结束类

服务器配置摘录

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 = 带有 { _ 的新 System.ServiceModel.NetTcpSecurity.Mode = SecurityMode.Transport, _.Transport = New System.ServiceModel.TcpTransportSecurity with {.ProtectionLevel = Net.Security.ProtectionLevel.Sign, .ClientCredentialType = TcpClientCredentialType.Windows} _} _}.....Dim 端点 As ServiceEndpoint = ServiceHostObject.AddServiceEndpoint(Contract, TCPBinding, "")端点(新 ProtoBuf.ServiceModel.ProtoEndpointBehavior)

解决方案

关于 Marc 的评论,他指出有一些方法可以使 protobuf-net 与 SvcUtil 或添加服务引用"一起工作;VS 命令,我发现 this发帖,他说:

<块引用>

Re Order=...,内容值得一看;如果他们想出不同的数字,有办法通过部分类来解决这个问题——一个丑陋的黑客,但 IIRC 有 ProtoPartialMember(或类似的)可以应用于类,但它谈论的是单个成员(属性/字段).

然后是这个 发帖,他说:

<块引用>

有两个选项可以解决这个问题;第一个(也是最简单的)是使用 WCF 在客户端和服务器之间共享合约程序集的能力.如果您可以共享 DTO 层,那将使事情变得简单.

第二种是在客户端添加额外的标记以提供线索.您可以通过分部类执行此操作,例如在单独的代码文件中(不要编辑生成的文件):

namespace YourNamespace {[ProtoContract(DataMemberOffset = 1)]/* 转移所有 DataMember 订单 */公共部分类 tbEmployee {}}

<块引用>

更明确的替代方法是:

namespace YourNamespace {[ProtoPartialMember(1, EmployeeID")][ProtoPartialMember(2, "EmployeeName")]公共部分类 tbEmployee {}}

We are using ProtoBuff.NET with our WCF service. ProtoBehavour has been applied to the interface, ProtoContract has been applied to the class & ProtoMember has been applied to the properties.

On the client side we have added the protobuff behavior to the app.config as below however when the client requests a object via the WCF service we receive a incorrect wire type error.

Removing the ProtoBuff behavior on the service results in the service working fine.

Can anybody please shed some light on what is happening or point us in the right direction.

We are using the NET TCP binding.

Client Configuration

<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>

Example Class

<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

Server Config Excerpts

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)

解决方案

In regard to Marc's comment where he stated that there were ways to make protobuf-net work along with SvcUtil or "Add Service Reference" VS command, I found this post, where he says:

Re Order=..., it would be worth checking the contents; if they are coming up with different numbers, there are ways to fix this via a partial class - an ugly hack, but IIRC there is ProtoPartialMember (or similar) that can be applied to the class, but which talks about an individual member (property/field).

Then there is this post, where he says:

There are 2 options for fixing this; the first (and easiest) is to use WCF's ability to share a contract assembly between client and server. If you can share the DTO layer, that'll keep things simple.

The second is to add additional markers at the client to give it a clue. You can do this via a partial class, for example in a separate code file (don't edit the generated file):

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

a more explicit alternative is:

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

这篇关于ProtoBuff.NET WCF - 客户端上的线类型错误不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆