Reputation: 1
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)
Upvotes: 0
Views: 944
Reputation: 3230
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 {}
}
Upvotes: 0
Reputation: 12680
If you are not sharing the service contract assemblies as suggested in marc's answer then you need a way to make WCF use the ProtoBuf serializer instead of the WCF default serializer in your client code. The problem is the ProtoBuf attribute markings in the service contract will not be in the WSDL document that is normally used to generate the service proxy in the client code.
Upvotes: 0