Получение обратных вызовов WCF для работы с netTcpBinding

У меня возникли проблемы с получением обратных вызовов, работающих с моим клиентом/сервером netTcpBinding WCF. Вот код... есть мысли?

Сервисная сторона

договор:

using System.Runtime.Serialization;
using System.ServiceModel;

namespace API.Interface
{
   [ServiceContract(CallbackContract = typeof(IServiceCallback))]
   public interface IMyService
   {
       [OperationContract]
       void DoSomething();
   }

   public interface IServiceCallback
   {
        [OperationContract(IsOneWay = true)]
        void OnCallback();
   }
}

услуга:

using System;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.Timers;
using API.Interface;

namespace API.Service
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class MyService : IMyService
    {
        public static IServiceCallback callback;
        public static Timer Timer;

        public void DoSomething()
        {
            Console.WriteLine("> Session opened at {0}", DateTime.Now);
            callback = OperationContext.Current.GetCallbackChannel<IServiceCallback>();

            Timer = new Timer(1000);
            Timer.Elapsed += OnTimerElapsed;
            Timer.Enabled = true;

        }

        void OnTimerElapsed(object sender, ElapsedEventArgs e)
        {
            callback.OnCallback();
        }
    }
}

Вот код, который я использую для запуска службы

        var service = new MyService();
        // Start up the WCF API
        var service = new ServiceHost(turboService);
        service.Open();

Вот App.Config

   <system.serviceModel>
    <services>
      <service name="API.Service.MyService">
        <endpoint address="" binding="netTcpBinding" bindingConfiguration=""
          contract="API.Interface.IMyService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
          contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:8732/MyService/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Клиентская сторона

CallbackService

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using USBAutomationTester.ServiceReference;

namespace USBAutomationTester
{
    [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
    public class CallbackService : IMyServiceCallback
    {
        public void OnCallback()
        {
            Console.WriteLine("> Received callback at {0}", DateTime.Now);
        }
    }
}

Подключение и вызов

 var instanceContext = new InstanceContext(new CallbackService());
 var service = new TurboValidateServiceClient(instanceContext);
 service.DoSomething();

App.Config

  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding_IMyService" />
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="net.tcp://localhost:8732/MyService/"
        binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ITurboValidateService"
        contract="ServiceReference.IMyService"
        name="NetTcpBinding_IMyService">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>

Я считаю, что у меня есть все необходимые части. Поиск в Google привел меня по нескольким разным путям без реального результата. Я вижу, как служба вызывает обратный вызов, но мой клиент никогда его не получает.

Заранее спасибо, я знаю, что это вопрос типа WCF 101, но на данный момент я в тупике.

ОБНОВЛЕНИЕ

На клиенте я получаю это исключение

«Входящее сообщение с действием не может быть обработано, поскольку оно предназначено для операции запрос-ответ, но на него нельзя ответить, так как свойство MessageId не задано».

с последующим

«Канал получил неожиданное входное сообщение с действием 'http://tempuri.org/IMyService/OnCallback' при закрытии. Вы должны закрывать свой канал только тогда, когда вы больше не ожидаете входящих сообщений».


person AndySousa    schedule 07.11.2013    source источник


Ответы (1)


Возможно, проблема в том, что к моменту срабатывания таймера контекст уже закрыт.

    public void DoSomething()
    {
        Console.WriteLine("> Session opened at {0}", DateTime.Now);
        callback = OperationContext.Current.GetCallbackChannel<IServiceCallback>();

        Timer = new Timer(1000);
        Timer.Elapsed += OnTimerElapsed;
        Timer.Enabled = true;

    }

    void OnTimerElapsed(object sender, ElapsedEventArgs e)
    {
        callback.OnCallback();
    }

Попробуйте применить обратный вызов к ICommunicationObject и проверить свойство State. Если для него не установлено значение Open, когда вы пытаетесь выполнить OnCallback, это ваша проблема.

person SouthShoreAK    schedule 07.11.2013
comment
это выглядело так, как будто оно было открыто на пару итераций, а затем закрыто. Я до сих пор не получил обратный вызов на клиенте. - person AndySousa; 07.11.2013
comment
Я переместил некоторые из своих деклараций и сделал их статичными... похоже, это помогло. Спасибо - person AndySousa; 07.11.2013