Protobuf-net WCF-ответ пуст - PullRequest
2 голосов
/ 26 мая 2011

У меня есть контракт WCF, описывающий метод тестирования, который просто возвращает экземпляр класса через WCF с использованием protobuf-net. Я могу сериализовать и десериализовать в тестовом приложении, но когда я делаю запрос через 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, и метод deserialize запускается, и он просто создает пустой экземпляр TestClass и выполняет итерацию по возвращаемым данным, но никогда не устанавливает никаких свойств.

О, я использовал Mex для генерации прокси.

EDIT

Вот сгенерированный MEX класс для TestClass

[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));
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 26 мая 2011

справа; Мекс / поколение не включает числа, но вы можете добавить их. В отдельном файле кода (то же пространство имен) добавьте

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

Иногда WCF помогает, иногда - боль (обратите внимание, это работает легко, если у вас есть общая сборка DTO на обоих концах).

Иногда WCF дает правильные числа для каждого DataMember, но постепенно - 1 - если , что происходит, есть твик, который вы можете использовать, чтобы просто сказать protobuf, чтобы использовать эти числа со смещением.

0 голосов
/ 26 мая 2011

Я думаю, что вы столкнулись с известной проблемой совместимости здесь.Пожалуйста, смотрите мой ответ на этот пост: На стороне клиента возвращаемое значение WCF Operation Contract равно нулю!Любое решение?

Вам необходимо определить сообщение 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
...