配置WCF客户端和服务以与protobuf net一起使用

配置WCF客户端和服务以与protobuf net一起使用,wcf,protobuf-net,datacontractserializer,custom-binding,Wcf,Protobuf Net,Datacontractserializer,Custom Binding,我决定就这件事提出一个新问题,也许是一个扩大的问题,因为在互联网上找不到关于这个问题的确切答案 我想使用protobuf-net对我的WCF客户端和服务之间交换的消息进行序列化/反序列化。该服务在Windows服务中自托管。客户机和服务都是以编程方式配置的,使用一个非常类似于wsHttpBinding的自定义绑定。服务引用代码是使用VisualStudio中的“添加服务引用”选项生成的。WCF服务上使用的ORM是EntityFramework 4,其代码是使用EF 4.x POCO Genera

我决定就这件事提出一个新问题,也许是一个扩大的问题,因为在互联网上找不到关于这个问题的确切答案

我想使用protobuf-net对我的WCF客户端和服务之间交换的消息进行序列化/反序列化。该服务在Windows服务中自托管。客户机和服务都是以编程方式配置的,使用一个非常类似于
wsHttpBinding
的自定义绑定。服务引用代码是使用VisualStudio中的“添加服务引用”选项生成的。WCF服务上使用的ORM是EntityFramework 4,其代码是使用EF 4.x POCO Generator生成的。关于我的服务配置的更多信息可以在我开始的一个问题中找到(在那里我描述了我当前的序列化程序是
DataContractSerialzizer

我只使用一个返回自定义DTO列表的服务操作测试了protobuf net。 以下是操作(请注意,我刚刚将代码复制粘贴到此处,可能有一些字段是用我的母语命名的,而不是英语):

当我使用“添加服务引用”生成引用代码时,我必须使用两种解决方法之一,以便让我的客户识别
协议和成员:

  • 为DTO使用共享程序集(在我的情况下,除了自定义DTO之外,这不是一个理想的解决方案,因为我将EF生成的POCO传递给客户端)
  • 使用
    ProtoPartialMember
    方法
我使用了这两种方法,我使用了protobuf-net的v1v2,所有的解决方案都产生了类似的结果,这让我相信我的客户根本没有反序列化。继续读下去

让我们考虑一下我使用了<代码> PrPoPrtualPrimult方法的情况。起初,我使用了v2。我喜欢

ProtoOperationBehavior
的使用方式。以下是要调用的服务操作:

    [ProtoBuf.ServiceModel.ProtoBehavior]
    public List<OsobaView> GetListOsobas()
    {
        return OsobaQueries.GetListOsobas();
    }
当然,以下是上述DTO的实施工作:

    [ProtoPartialMember(1, "ID")]
    [ProtoPartialMember(2, "Prezime")]
    [ProtoPartialMember(3, "Ime")]
    [ProtoPartialMember(4, "Adresa")]
    [ProtoPartialMember(5, "DatumRodjenja")]
    [ProtoPartialMember(6, "JMBG")]
    [ProtoContract]
    public partial class OsobaView
    {
    }
现在,当我从客户端调用此服务操作时,我得到
null
。但是小提琴手不同意。在回应标题中,它清楚地说:

    Content-Length: 1301963
    Content-Type: application/soap+xml; charset=utf-8
…并在邮件正文中:

    <s:Body>
      <GetListOsobasResponse xmlns="http://tempuri.org/">
        <proto>CkMIpHES .../* REALLY LONG RESPONSE */... IyMDAxOA==</proto>
      </GetListOsobasResponse>
    </s:Body>
我启动了它,调用了操作,这次结果不是
null
。这次是一个空白字段列表。再一次,Fiddler无法同意,因为它再次说出了与之前相同的话。相同的内容长度和相同的消息正文

这是怎么回事

另外,如果有价值的话,这里是WCF配置:

    CustomBinding customBinding = new CustomBinding();
    customBinding.CloseTimeout = TimeSpan.FromMinutes(10);
    customBinding.OpenTimeout = TimeSpan.FromMinutes(10);
    customBinding.ReceiveTimeout = TimeSpan.FromMinutes(10);
    customBinding.SendTimeout = TimeSpan.FromMinutes(10);
    HttpsTransportBindingElement httpsBindingElement = new HttpsTransportBindingElement();
    httpsBindingElement.AllowCookies = false;
    httpsBindingElement.BypassProxyOnLocal = false;
    httpsBindingElement.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
    httpsBindingElement.MaxBufferPoolSize = 20480000;
    httpsBindingElement.MaxBufferSize = 20480000;
    httpsBindingElement.MaxReceivedMessageSize = 20480000;
    httpsBindingElement.RequireClientCertificate = true;
    httpsBindingElement.UseDefaultWebProxy = true;
    TransportSecurityBindingElement transportSecurityElement = new TransportSecurityBindingElement();
    transportSecurityElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(new UserNameSecurityTokenParameters());
    transportSecurityElement.EndpointSupportingTokenParameters.SetKeyDerivation(false);
    TransactionFlowBindingElement transactionFlowElement = new TransactionFlowBindingElement();
    TextMessageEncodingBindingElement textMessageEncoding = new TextMessageEncodingBindingElement();
    textMessageEncoding.MaxReadPoolSize = 20480000;
    textMessageEncoding.MaxWritePoolSize = 20480000;
    textMessageEncoding.ReaderQuotas = XmlDictionaryReaderQuotas.Max;
    ReliableSessionBindingElement reliableSessionElement = new ReliableSessionBindingElement();
    reliableSessionElement.ReliableMessagingVersion = ReliableMessagingVersion.WSReliableMessagingFebruary2005;
    customBinding.Elements.Add(transportSecurityElement);
    customBinding.Elements.Add(transactionFlowElement);
    customBinding.Elements.Add(textMessageEncoding);
    customBinding.Elements.Add(reliableSessionElement);
    customBinding.Elements.Add(httpsBindingElement);

    EndpointAddress endpoint = new EndpointAddress(new Uri(ServiceAddress));
    Service.Proxy = new BazaService.BazaClient(customBinding, endpoint);
    Service.Proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, CertificateSubject);
    CustomBehavior behavior = Service.Proxy.Endpoint.Behaviors.Find<CustomBehavior>();
    if (behavior == null)
    {
        Service.Proxy.Endpoint.Behaviors.Add(new CustomBehavior()); // message inspector
    }
    Service.Proxy.Endpoint.Contract.Behaviors.Add(new CyclicReferencesAwareContractBehavior(true));
    Service.Proxy.Endpoint.Behaviors.Add(new ProtoBuf.ServiceModel.ProtoEndpointBehavior());

    /* code used for protobuf-net v2

    OperationDescription op = Service.Proxy.Endpoint.Contract.Operations.Find("GetListOsobas");
    if (op != null)
    {
        DataContractSerializerOperationBehavior dcsBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
        if (dcsBehavior != null)
            op.Behaviors.Remove(dcsBehavior);
        op.Behaviors.Add(new ProtoBuf.ServiceModel.ProtoOperationBehavior(op));
    } */

    Service.Proxy.ClientCredentials.UserName.UserName = LogOn.UserName;
    Service.Proxy.ClientCredentials.UserName.Password = LogOn.Password;
    Service.Proxy.Open();
CustomBinding CustomBinding=new CustomBinding();
customBinding.CloseTimeout=TimeSpan.FromMinutes(10);
customBinding.OpenTimeout=TimeSpan.FromMinutes(10);
customBinding.ReceiveTimeout=TimeSpan.FromMinutes(10);
customBinding.SendTimeout=TimeSpan.FromMinutes(10);
HttpsTransportBindingElement httpsBindingElement=新的HttpsTransportBindingElement();
httpsBindingElement.AllowCookies=false;
httpsBindingElement.BypassProxyOnLocal=false;
httpsBindingElement.HostNameComparisonMode=HostNameComparisonMode.strong通配符;
httpsBindingElement.MaxBufferPoolSize=20480000;
httpsBindingElement.MaxBufferSize=20480000;
httpsBindingElement.MaxReceivedMessageSize=20480000;
httpsBindingElement.RequireClientCertificate=true;
httpsBindingElement.UseDefaultWebProxy=true;
TransportSecurityBindingElement transportSecurityElement=新的TransportSecurityBindingElement();
transportSecurityElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(新UserNameSecurityTokenParameters());
transportSecurityElement.EndpointSupportingTokenParameters.SetKeyDerivation(false);
TransactionFlowBindingElement transactionFlowElement=新TransactionFlowBindingElement();
TextMessageEncodingBindingElement textMessageEncoding=新的TextMessageEncodingBindingElement();
textMessageEncoding.MaxReadPoolSize=20480000;
textMessageEncoding.MaxWritePoolSize=20480000;
textMessageEncoding.ReaderQuotas=XmlDictionaryReaderQuotas.Max;
ReliableSessionBindingElement reliableSessionElement=新的ReliableSessionBindingElement();
reliableSessionElement.ReliableMessagingVersion=ReliableMessagingVersion.WSReliableMessagingFebruary2005;
customBinding.Elements.Add(transportSecurityElement);
customBinding.Elements.Add(transactionFlowElement);
customBinding.Elements.Add(textMessageEncoding);
customBinding.Elements.Add(reliableSessionElement);
customBinding.Elements.Add(httpsBindingElement);
EndpointAddressEndpoint=新的EndpointAddress(新Uri(ServiceAddress));
Service.Proxy=新的BazaService.BazaClient(customBinding,端点);
Service.Proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser,StoreName.My,X509FindType.FindBySubjectName,CertificateSubject);
CustomBehavior=Service.Proxy.Endpoint.Behaviors.Find();
if(行为==null)
{
Service.Proxy.Endpoint.Behaviors.Add(新的CustomBehavior());//消息检查器
}
Service.Proxy.Endpoint.Contract.Behaviors.Add(新的CycleCreferencesWareContractBehavior(true));
添加(新ProtoBuf.ServiceModel.ProtoEndpointBehavior());
/*用于protobuf net v2的代码
OperationDescription op=Service.Proxy.Endpoint.Contract.Operations.Find(“GetListOsobas”);
如果(op!=null)
{
DataContractSerializePropertyBehavior=op.Behaviors.Find();
if(dcsBehavior!=null)
op.Behavior.Remove(dcsBehavior);
添加(新的ProtoBuf.ServiceModel.ProtoOperationBehavior(op));
} */
Service.Proxy.ClientCredentials.UserName.UserName=LogOn.UserName;
Service.Proxy.ClientCr
    Content-Length: 1301963
    Content-Type: application/soap+xml; charset=utf-8
    <s:Body>
      <GetListOsobasResponse xmlns="http://tempuri.org/">
        <proto>CkMIpHES .../* REALLY LONG RESPONSE */... IyMDAxOA==</proto>
      </GetListOsobasResponse>
    </s:Body>
    Service.Proxy.Endpoint.Behaviors
        .Add(new ProtoBuf.ServiceModel.ProtoEndpointBehavior());
    CustomBinding customBinding = new CustomBinding();
    customBinding.CloseTimeout = TimeSpan.FromMinutes(10);
    customBinding.OpenTimeout = TimeSpan.FromMinutes(10);
    customBinding.ReceiveTimeout = TimeSpan.FromMinutes(10);
    customBinding.SendTimeout = TimeSpan.FromMinutes(10);
    HttpsTransportBindingElement httpsBindingElement = new HttpsTransportBindingElement();
    httpsBindingElement.AllowCookies = false;
    httpsBindingElement.BypassProxyOnLocal = false;
    httpsBindingElement.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
    httpsBindingElement.MaxBufferPoolSize = 20480000;
    httpsBindingElement.MaxBufferSize = 20480000;
    httpsBindingElement.MaxReceivedMessageSize = 20480000;
    httpsBindingElement.RequireClientCertificate = true;
    httpsBindingElement.UseDefaultWebProxy = true;
    TransportSecurityBindingElement transportSecurityElement = new TransportSecurityBindingElement();
    transportSecurityElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(new UserNameSecurityTokenParameters());
    transportSecurityElement.EndpointSupportingTokenParameters.SetKeyDerivation(false);
    TransactionFlowBindingElement transactionFlowElement = new TransactionFlowBindingElement();
    TextMessageEncodingBindingElement textMessageEncoding = new TextMessageEncodingBindingElement();
    textMessageEncoding.MaxReadPoolSize = 20480000;
    textMessageEncoding.MaxWritePoolSize = 20480000;
    textMessageEncoding.ReaderQuotas = XmlDictionaryReaderQuotas.Max;
    ReliableSessionBindingElement reliableSessionElement = new ReliableSessionBindingElement();
    reliableSessionElement.ReliableMessagingVersion = ReliableMessagingVersion.WSReliableMessagingFebruary2005;
    customBinding.Elements.Add(transportSecurityElement);
    customBinding.Elements.Add(transactionFlowElement);
    customBinding.Elements.Add(textMessageEncoding);
    customBinding.Elements.Add(reliableSessionElement);
    customBinding.Elements.Add(httpsBindingElement);

    EndpointAddress endpoint = new EndpointAddress(new Uri(ServiceAddress));
    Service.Proxy = new BazaService.BazaClient(customBinding, endpoint);
    Service.Proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, CertificateSubject);
    CustomBehavior behavior = Service.Proxy.Endpoint.Behaviors.Find<CustomBehavior>();
    if (behavior == null)
    {
        Service.Proxy.Endpoint.Behaviors.Add(new CustomBehavior()); // message inspector
    }
    Service.Proxy.Endpoint.Contract.Behaviors.Add(new CyclicReferencesAwareContractBehavior(true));
    Service.Proxy.Endpoint.Behaviors.Add(new ProtoBuf.ServiceModel.ProtoEndpointBehavior());

    /* code used for protobuf-net v2

    OperationDescription op = Service.Proxy.Endpoint.Contract.Operations.Find("GetListOsobas");
    if (op != null)
    {
        DataContractSerializerOperationBehavior dcsBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
        if (dcsBehavior != null)
            op.Behaviors.Remove(dcsBehavior);
        op.Behaviors.Add(new ProtoBuf.ServiceModel.ProtoOperationBehavior(op));
    } */

    Service.Proxy.ClientCredentials.UserName.UserName = LogOn.UserName;
    Service.Proxy.ClientCredentials.UserName.Password = LogOn.Password;
    Service.Proxy.Open();