2010-04-11 4 views
0

Voici le code du serveur:Duplex contrat GetCallbackChannel retourne toujours une valeur nulle instance

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.ServiceModel; 
    using System.Runtime.Serialization; 
    using System.ServiceModel.Description; 



    namespace Console_Chat 
{ 


    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IMyCallbackContract))] 
    public interface IMyService 
    { 
     [OperationContract(IsOneWay = true)] 
     void NewMessageToServer(string msg); 

     [OperationContract(IsOneWay = false)] 
     bool ServerIsResponsible(); 

    } 



    [ServiceContract] 
    public interface IMyCallbackContract 
    { 
     [OperationContract(IsOneWay = true)] 
     void NewMessageToClient(string msg); 

     [OperationContract(IsOneWay = true)] 
     void ClientIsResponsible(); 



    } 


    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] 
    public class MyService : IMyService 
    { 

     public IMyCallbackContract callback = null; 

    /* 
    { 
      get 
      { 
       return OperationContext.Current.GetCallbackChannel<IMyCallbackContract>(); 
      } 
     } 
     */ 

     public MyService() 
     { 
      callback = OperationContext.Current.GetCallbackChannel<IMyCallbackContract>(); 
     } 

     public void NewMessageToServer(string msg) 

     { 
      Console.WriteLine(msg); 
     } 

     public void NewMessageToClient(string msg) 
     { 

      callback.NewMessageToClient(msg); 
     } 


     public bool ServerIsResponsible() 
     { 
      return true; 
     } 

    } 




    class Server 
    { 
     static void Main(string[] args) 
     { 
      String msg = "none"; 


      ServiceMetadataBehavior behavior = new 
      ServiceMetadataBehavior(); 


      ServiceHost serviceHost = new 
      ServiceHost(
      typeof(MyService), 
      new Uri("http://localhost:8080/")); 

      serviceHost.Description.Behaviors.Add(behavior); 

      serviceHost.AddServiceEndpoint(
       typeof(IMetadataExchange), 
       MetadataExchangeBindings.CreateMexHttpBinding(), 
       "mex"); 


      serviceHost.AddServiceEndpoint(
       typeof(IMyService), 
       new WSDualHttpBinding(), 
       "ServiceEndpoint" 
       ); 

      serviceHost.Open(); 
      Console.WriteLine("Server is up and running"); 

      MyService server = new MyService(); 
      server.NewMessageToClient("Hey client!"); 
/* 

      do 
      { 
       msg = Console.ReadLine(); 

       // callback.NewMessageToClient(msg); 


      } while (msg != "ex"); 

    */ 
      Console.ReadLine();  

     } 
    } 
} 

Voici du client:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ServiceModel; 
using System.Runtime.Serialization; 
using System.ServiceModel.Description; 
using Console_Chat_Client.MyHTTPServiceReference; 



namespace Console_Chat_Client 
{ 
    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IMyCallbackContract))] 
    public interface IMyService 
    { 
     [OperationContract(IsOneWay = true)] 
     void NewMessageToServer(string msg); 

     [OperationContract(IsOneWay = false)] 
     bool ServerIsResponsible(); 

    } 



    [ServiceContract] 
    public interface IMyCallbackContract 
    { 
     [OperationContract(IsOneWay = true)] 
     void NewMessageToClient(string msg); 

     [OperationContract(IsOneWay = true)] 
     void ClientIsResponsible(); 

    } 




    public class MyCallback : Console_Chat_Client.MyHTTPServiceReference.IMyServiceCallback 
    { 

     static InstanceContext ctx = new InstanceContext(new MyCallback()); 

     static MyServiceClient client = new MyServiceClient(ctx); 



     public void NewMessageToClient(string msg) 
     { 
      Console.WriteLine(msg); 
     } 

     public void ClientIsResponsible() 
     { 

     } 


       class Client 
       { 
        static void Main(string[] args) 
        { 
         String msg = "none"; 





         client.NewMessageToServer(String.Format("Hello server!")); 


         do 
         { 
          msg = Console.ReadLine(); 
          if (msg != "ex") 
           client.NewMessageToServer(msg); 
          else client.NewMessageToServer(String.Format("Client terminated")); 
         } while (msg != "ex"); 
        } 
       } 






    } 
} 

rappel = OperationContext.Current.GetCallbackChannel(); Cette ligne jette une exception NullReferenceException, quel est le problème?

Merci!

Répondre

3

Vous ne pouvez pas démarrer un service WCF avec un contrat de rappel et essayer immédiatement d'exécuter un rappel client. Il n'y a pas encore de clients.

Dans votre code, je vous vois instancier manuellement un MyService et essayer d'exécuter une méthode de rappel. Cela ne fonctionnera tout simplement pas. Si vous souhaitez utiliser la méthode GetCallbackChannel, vous devez le faire lorsqu'il existe réellement un canal, c'est-à-dire dans le contexte d'une opération réelle appelée par un client WCF distant. Sinon, il n'y a pas de OperationContext actuel et vous obtiendrez une exception de référence nulle car OperationContext.Current renvoie null.

Les rappels sont destinés à être utilisés avec des opérations de maintenance de longue durée. Par exemple:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] 
public class MyService : IMyService 
{ 
    // One-way method 
    public void PerformLongRunningOperation() 
    { 
     var callback = 
      OperationContext.Current.GetCallbackChannel<IMyCallbackContract>(); 
     var result = DoLotsOfWork(); 
     callback.LongRunningOperationFinished(result); 
    } 
} 

Pour tester cela, vous devez créer effectivement un client - lancer un nouveau projet, ajouter une référence à ce service, mettre en œuvre le rappel que l'importateur génère, créez un InstanceContext avec le rappel, créez le proxy client en utilisant ce InstanceContext, et finalement invoquer sa méthode PerformLongRunningOperation.

Si vous essayez de développer un pub/sous-implémentation, où les clients ne lancent pas réellement les opérations mais s'enregistrent simplement pour recevoir un rappel, jetez un oeil à cette page: Using Callback Contracts in WCF for Asynchronous Publish/Subscribe Event-Style Communication.

+3

deadlink !!!!!!! – David

+0

Lien est mort ... –

+0

Commencez [ici] (http://stackoverflow.com/questions/8193518/any-good-wcf-publish-subscribe-framework-tutorials-out-there), peut-être. Ce lien suggère plusieurs sites avec des liens de travail pour en savoir plus sur pub/sub. – shipr

Questions connexes