Question

J'ai des problèmes pour que des rappels fonctionnent avec mon client / serveur WCF NetTCPBinding. Voici le code ... des pensées?

Côté service

Contrat:

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

service:

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

Voici le code que j'utilise pour démarrer le service

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

Voici l'application.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>

Côté client

Rappel

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

Connexion et appel

 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>

Je crois que j'ai toutes les pièces nécessaires. Google Searching m'a conduit à plusieurs chemins différents sans résultat réel. Je peux voir le service appeler le rappel, mais mon client ne l'obtient jamais.

Merci d'avance, je sais que c'est une question de type WCF 101, mais je suis perplexe à ce stade.

METTRE À JOUR

Sur le client, je reçois cette exception

"Le message entrant avec action n'a pas pu être traité car il est ciblé lors d'une opération de demande, mais ne peut pas être répondu car la propriété MessageID n'est pas définie."

suivie par

"Le canal a reçu un message d'entrée inattendu avec l'action 'http://tempuri.org/imyservice/oncallback«Pendant la fermeture. Vous ne devez fermer votre chaîne que lorsque vous n'attendez plus de messages d'entrée. "

Était-ce utile?

La solution

Il se peut que le problème soit que le contexte est déjà fermé au moment où votre minuterie tire.

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

Essayez de lancer votre rappel à ICommunicationObject et vérifier le State propriété. S'il n'est pas réglé sur Open Quand tu essaie OnCallback, c'est ton problème.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top