【问题标题】:Protobuf-net WCF response is emptyProtobuf-net WCF 响应为空
【发布时间】:2013-03-09 07:36:24
【问题描述】:

我有一个 WCF 契约,它概述了一个测试方法,它使用 protobuf-net 在 WCF 中返回一个类的实例。我可以在测试应用程序中序列化和反序列化,但是当我通过 WCF 发出请求时,类实例存在的响应,但它的所有属性都是空的。

以下是相关的配置文件和类定义:

[ProtoContract]
public class TestClass
{
    [ProtoMember(1)]
    public int TestInt { get; set; }

    [ProtoMember(2)]
    public string TestString { get; set; }
}

...

[ServiceContract]
public interface ITestService
{
    [OperationContract]
    [ProtoBehavior]
    TestClass RunTest(int x);
}

...

<extensions>
    <behaviorExtensions>
        <add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, protobuf-net, Version=1.0.0.282, Culture=neutral, PublicKeyToken=257b51d87d2e4d67" />
    </behaviorExtensions>
</extensions>

<endpointBehaviors>
    <behavior name="Proto.Default.EndpointBehavior">
        <protobuf />
    </behavior>
</endpointBehaviors>
<serviceBehaviors>
    <behavior name="Proto.Default.ServiceBehavior">
      <serviceDebug includeExceptionDetailInFaults="true" />
      <serviceMetadata />
      <serviceAuthorization principalPermissionMode="None" />
      <serviceThrottling    maxConcurrentCalls="250"
                            maxConcurrentSessions="200"
                            maxConcurrentInstances="10" />
    </behavior>
</serviceBehaviors>

...

<services>
    <service name="WcfTestService" behaviorConfiguration="Proto.Default.ServiceBehavior">
    <endpoint address=""    binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ITestService"   contract="ITestService" behaviorConfiguration="Proto.Default.EndpointBehavior" />
    <endpoint address="mex" binding="customBinding" bindingConfiguration="myMexTcpBinding" contract="IMetadataExchange" />
    <host>
        <baseAddresses>
            <add baseAddress="net.tcp://localhost:2517/TestService" />
        </baseAddresses>
    </host>
</service>

...

<client>
   <endpoint address="net.tcp://localhost:2517/TestService"
    binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ITestService"
    contract="ITestService" name="TestService"
    behaviorConfiguration="Proto.Default.EndpointBehavior">
    <identity>
        <dns value="localhost" />
    </identity>
</endpoint>
</client>

我可以调试服务并查看请求。 TestClass 对象被创建并返回。我单步执行了 protobuf-net 源代码,反序列化方法运行,它只是创建了一个空白的 TestClass 实例并遍历返回的数据,但从不设置任何属性。

哦,我是用 Mex 生成代理的。

编辑

这是为 TestClass 生成的 MEX 类

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="TestClass", Namespace="http://schemas.datacontract.org/2004/07/TestProject")]
[System.SerializableAttribute()]
public partial class TestClass : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {

    [System.NonSerializedAttribute()]
    private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

    [System.Runtime.Serialization.OptionalFieldAttribute()]
    private int TestIntField;

    [System.Runtime.Serialization.OptionalFieldAttribute()]
    private string TestStringField;

    [global::System.ComponentModel.BrowsableAttribute(false)]
    public System.Runtime.Serialization.ExtensionDataObject ExtensionData {
        get {
            return this.extensionDataField;
        }
        set {
            this.extensionDataField = value;
        }
    }

    [System.Runtime.Serialization.DataMemberAttribute()]
    public int TestInt {
        get {
            return this.TestIntField;
        }
        set {
            if ((this.TestIntField.Equals(value) != true)) {
                this.TestIntField = value;
                this.RaisePropertyChanged("TestInt");
            }
        }
    }

    [System.Runtime.Serialization.DataMemberAttribute()]
    public string TestString {
        get {
            return this.TestStringField;
        }
        set {
            if ((object.ReferenceEquals(this.TestStringField, value) != true)) {
                this.TestStringField = value;
                this.RaisePropertyChanged("TestString");
            }
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

【问题讨论】:

  • 你能显示 Mex 生成的代理吗?有一些方法可以强制代理玩得很好,但我需要看看。特别是,我关注标记为 DataMember 的成员及其属性
  • 我贴出了上面为TestClass生成的代码。

标签: wcf protobuf-net


【解决方案1】:

对; Mex/generation 没有包含这些数字,但您可以添加它们。在单独的代码文件(相同的命名空间)中,添加

[ProtoContract]
[ProtoPartialMember(1, "TestInt")]
[ProtoPartialMember(2, "TestString")]
partial class TestClass {}

WCF 有时会有所帮助,有时会很痛苦(请注意,如果两端都有共享的 DTO 程序集,它会很容易工作)。

有时 WCF 会在每个 DataMember 上给出正确的数字,但会偏离 1 - 如果 发生这种情况,您可以使用一个调整来告诉 protobuf 使用这些带有偏移量的数字。

【讨论】:

  • 好吧,这里真的不能怪 WCF。使用自定义序列化属性(即 ProtoMember 与 DataMember)意味着 proto 缓冲区行为实现将负责通过实现 IWsdlExportExtension 为 WSDL 生成适当的模式详细信息。由于不是,它将默认为成员的字母顺序。
  • @Drew 并且为了这个双重目的,protobuf-net 非常高兴地使用 DataContract/DataMember 属性:)
  • @Drew - 但是,该界面对我来说是一个新界面;我去看看
  • @Marc Gravell 您也可以同时使用 DataMemberAttribute 和 ProtoMemberAttribute,其中 DMA 可以帮助您进行排序,而 PMA 可以帮助您提供所有 protobuf 特定的支持。然后,您无需对 IWsdlExport/ImportExtension 执行任何特定操作。缺点是 DMA 的 Order 和 PMA 的 Tag 之间的顺序概念需要更多的编码和重复。我打赌你可以让它与 IWsdlExportExtension 一起使用,def。看看吧。
  • @Andy 分享组合对于这个来说是一件轻而易举的事——到目前为止,对于已经是一个非常自定义的场景来说,这是最简单的选择
【解决方案2】:

我认为您在这里遇到了著名的互操作性问题。请看我对这篇文章的回答: At client side, return value of WCF Operation Contract is null ! Any solution?

您需要识别客户端代码所期望的 Soap 消息和正确的代码,以便与服务返回的 Soap 消息保持同步。

在此示例中,您可以通过以下方式确定客户端期望响应消息的格式,

a. creating Service stub from WSDL using WSDL /serverInterface
b. Create a class implimenting the Service stub
c. Host the WebService in IIS and browse the help page
d. Click on operation called from list.
e. Help page shows the expected request and response soap message

【讨论】:

  • 在这种情况下,不会(相当)显示底层的预期格式...除非您可以在头脑中解码/编码 protobufs :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多