2012-03-28 87 views
0

我們在我們的WCF服務中使用ProtoBuff.NET。 ProtoBehavour已經應用到界面上,ProtoContract已經應用到類& ProtoMember已經應用到了屬性中。ProtoBuff.NET WCF - 客戶端上的線路類型錯誤

在客戶端,我們已經將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) 
+0

抱歉,延遲;你能澄清一下:連接的另一端 - 是使用相同的類型(彙編共享)還是使用生成的代理類型(svcutil/etc)?兩者都可以工作 - 但我需要知道哪個要正確回答。 – 2012-03-29 18:36:20

回答

0

如果您沒有按照marc的answer中的建議共享服務協議程序集,那麼您需要一種方法使WCF在客戶端代碼中使用ProtoBuf序列化程序,而不是WCF默認序列化程序。問題是服務合約中的ProtoBuf屬性標記不會位於通常用於在客戶端代碼中生成服務代理的WSDL文檔中。

+0

謝謝 - 如果您不共享程序集,那麼推薦使用protobuff.net的做法是什麼? – Luke 2012-03-29 06:09:37

+0

使用「添加服務引用」或使用SvcUtil自動生成服務代理在使用ProtoBuf時確實不會爲您帶來任何收益。原因是您必須使用ProtoMember屬性完全按照在服務合同中進行註釋來生成代碼。如果你搞砸了或重新生成了代理,那麼你回到了現在看到的。您可以共享服務合同代碼,但是您可以構建和維護兩個服務合同(客戶端和服務)。如果您打算使用ProtoBuf,請堅持共享服務合約程序集並節省一些工作量。 – 2012-03-29 12:42:01

+0

@Sixto實際上,有辦法,使這項工作 – 2012-03-29 18:35:25

0

關於馬克的評論,他指出,有辦法讓protobuf網工作,SvcUtil工具沿着或「添加服務引用」 VS命令,我發現this後,他說:

回覆Order = ...,這將是值得檢查的內容;如果他們想出不同的數字,有辦法通過一個部分課程來解決這個問題 - 一個醜陋的黑客,但IIRC有ProtoPartialMember(或類似的),可以應用於課堂,但談論一個單獨的成員(財產/領域)。

再有就是this後,他說:

有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 {} 
}