SlideShare a Scribd company logo
SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ;
WCF i SignalR
La idea és aconseguir que un servei WCF on podem tenir allotjades les operacions de negoci d’una aplicació, pugui
donar un feedback del que està fent en temps real a l’usuari de l’aplicació.




Per poder fer això de manera molt fàcil, utilitzaré el VS2012 Professional, el Framework 4.5, i dues llibreries RC,
Microsoft ASP.NET SignalR SystemWeb i Microsoft ASP.NET SignalR Client.
SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ;
Partirem de que tenim una aplicació client “activa”, en el meu cas i com a exemple, feta amb Winforms, que es
connecta a un servei que té operacions de negoci fet amb WCF.

Ara doncs es tracta d’aprofitar la potencia de SignalR per poder fer que el servidor sigui capaç d’informar al client del
que està passat en el procés de negoci invocat.

Primer de tot, crearem el servidor de missatges.

    1.   Crear un projecte Web buit.
    2.   Afegir refèrencia a Microsoft ASP.NET SignalR SystemWeb amb Nuget.
    3.   Afegir Global.asax.
    4.   Crear un Hub, amb les operacions que invocarem, i en la seva implementació i posarem les operacions
         dinàmiques que subscriuran els clients.

Mirar video1: http://youtu.be/g0JiRbpK0l8



Un cop tenim el servidor de missatges “SRServer”, preparem el servei de negoci i l’aplicació client per poder
treballar com a clients del servei de missatgeria. En aquest cas, l’ aplicació client només escoltarà, o ben dit, rebrà
missatges i el servei n’enviarà. Això no vol dir que no puguin fer les dues feines els dos.

A ambdós projectes li afegim la llibreria i Microsoft ASP.NET SignalR Client, amb Nuget package manager.

Un cop fet això implementarem les subscripcions del client winforms.

En el codi del form1 i declarem unes variables:

private string urlmessenger = "http://localhost:15560/";
private string hubproxy = "BusinessMessenger";
HubConnection hubConnection = null;



Sobreescrivim el delegat de l’event “OnShown”:

         protected override void OnShown(EventArgs e)
          {
              base.OnShown(e);

              hubConnection = new HubConnection(urlmessenger);
              //Creem el proxy
              var messageHub = hubConnection.CreateHubProxy(hubproxy);
              var schu = TaskScheduler.FromCurrentSynchronizationContext();
              // ens subscrivim als metodes dinàmics del servidor
              messageHub.On<string>("sendmessage", message =>
              {
                  // do our work on the UI thread
                  Task.Factory.StartNew(
                      () =>
                      {
                          this.textBoxConsole.ForeColor = Color.White;
                          this.textBoxConsole.AppendText(message + Environment.NewLine);
                      },
                      CancellationToken.None,
                      TaskCreationOptions.None,
                      schu
                      );
              });
              messageHub.On<string>("sendBCmessage", message =>
              {
                  // do our work on the UI thread
SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ;
                   Task.Factory.StartNew(
                       () =>
                       {
                           this.textBoxConsole.ForeColor = Color.Yellow;
                           this.textBoxConsole.AppendText(message + Environment.NewLine);
                       },
                       CancellationToken.None,
                       TaskCreationOptions.None,
                       schu
                       );
              });
              hubConnection.Start().ContinueWith(task =>
              {

                   if (task.IsFaulted)
                   {
                       task.ContinueWith((result) =>
                       {
                           textBoxConsole.ForeColor = Color.Red;
                           textBoxConsole.AppendText(
                              String.Format("Hi ha un error obrint la conexió: {0}{1}",
                              result.Exception.GetBaseException(), Environment.NewLine));
                       }
                           , schu);

                  }
                  else
                  {
                      task.ContinueWith((result) =>
                      {
                          textBoxConsole.ForeColor = Color.Green;
                          textBoxConsole.AppendText(
                         String.Format("La conexió s'ha obert correctament -ConnectionId:[{0}]-{1}",
                         hubConnection.ConnectionId, Environment.NewLine));
                      }, schu);
                  }
              }).Wait();

              EnableControls();

         }

         private void EnableControls()
         {
             this.button1.Enabled = true;
             this.button2.Enabled = true;
             this.textBoxConsole.Enabled = true;
         }



Un cop fet això ja tenim el client subscrit a dos funcions del servidor per rebre missatges.
SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ;
Si ens hi fixem tenim un identificador de connexió. Aquest és el que haurà de fer servir el servei en la instància que
serveix en cada moment al client. I per tant d’alguna manera hem de passar-lo al servei. Com que els serveis podem
utilitzar-los de moltes maneres, amb sessions, sense, podem passar sempre per paràmetre l ‘id de connexió, ..., bé,
pensem. Si el passem com a paràmetre, hauríem de modificar totes les operacions de la interfície que voléssim que
enviéssim missatges, i si el client ja el tenim implementat, modificar totes les crides a aquestes operacions.
Imaginem-nos que en tenim moltes, quin rotllo. I imaginem que moltes aplicacions accedeixen a operacions del
servei de negoci, BUA!!!!!. I el codi que picarem no el podrem reutilitzar......pensem.

Bé, si no volem fer res de tot això, i volem que sempre passi el id cap al servei, independentment de com està
instanciat, si permet sessions o no, i de com tracta la concurrència, la millor manera es mitjançant un paràmetre de
capçalera. Si nosaltres som capaços de modificar la connexió client de tal manera que a cada crida d’operació li
afegim una capçalera amb el id de connexió, i a les operacions del servei que vulguin enviar un missatge al client,
puguin obtenir el id de connexió d’aquest, ja ho tenim solucionat.

Per fer-ho ens creem una classe que implementarà dues interfícies del namespace System.ServiceModel.Dispacher i
System.ServideModel.Description. I en el mètode BeforeSendRequest modificarem la capçalera del missatge.

I després, quan creem la connexió li afegirem aquesta classe com a nou comportament del client.

   public class WcfClientInspector : IClientMessageInspector, IEndpointBehavior
    {
        static string _namespace = "http://soacat.blogspot.com";

         private string _messengerConnectionId = string.Empty;

         public WcfClientInspector(string messengerConnectionId)
         {
             _messengerConnectionId = messengerConnectionId;
         }
         public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply,
             object correlationState)
         {

         }

         public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,
             System.ServiceModel.IClientChannel channel)
         {
              MessageHeader<string> header =
                  new MessageHeader<string>(_messengerConnectionId);
              request.Headers.Add(header.GetUntypedHeader("MessengerConnectionId", _namespace));
              return null;

         }

         public void AddBindingParameters(ServiceEndpoint endpoint,
             System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
         {

         }

         public void ApplyClientBehavior(ServiceEndpoint endpoint,
             ClientRuntime clientRuntime)
         {
             clientRuntime.MessageInspectors.Add(this);
         }

         public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
             EndpointDispatcher endpointDispatcher)
         {

         }
SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ;

         public void Validate(ServiceEndpoint endpoint)
         {

         }
    }



Ara modifiquem els delegats dels events del botons per tal de que invoquin les operacions del servei, afegint el
comportament nou.

      private async void button1_Click(object sender, EventArgs e)
         {
             button1.Enabled = false;
             RefOrderService.IOrders cliordres = CreateAndOpenClient();

              await cliordres.ProcessOrdersAsync().ContinueWith((r)=>{

                   CloseClient((ICommunicationObject)cliordres);
                   button1.Enabled = true;

              }, TaskScheduler.FromCurrentSynchronizationContext());



         }

         private async void button2_Click(object sender, EventArgs e)
         {
             button2.Enabled = false;
             RefOrderService.IOrders cliordres = CreateAndOpenClient();

              await cliordres.MailingAsync().ContinueWith((s) =>
              {
                  textBoxConsole.ForeColor = Color.Blue;
                  textBoxConsole.AppendText(string.Format("{0}-{1}", s.Result, Environment.NewLine));
                  this.textBoxConsole.SelectionStart = this.textBoxConsole.Text.Length;
                  this.textBoxConsole.ScrollToCaret();
                  CloseClient((ICommunicationObject)cliordres);
                  button2.Enabled = true;

              }, TaskScheduler.FromCurrentSynchronizationContext());



         }

        private RefOrderService.IOrders CreateAndOpenClient()
        {
            RefOrderService.OrdersClient client = new RefOrderService.OrdersClient();
            client.Endpoint.EndpointBehaviors.Add(new
WcfClientInspector(hubConnection.ConnectionId));

              client.Open();
              return client;
         }
         private void CloseClient(ICommunicationObject comobj){
             comobj.Close();
         }



Ara ja només ens falta el servei de negoci. Primer haurà de poder recuperar la el id de connexió del client cap el
servei de missatges, i després saber com enviar-li un missatge. Farem una funció senzilla al servei, que llegira la
capçalera requerida.
SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ;


        private string GetClientMessengerConnectionId()
           {
               int pos=OperationContext.Current.
                   IncomingMessageHeaders.FindHeader("MessengerConnectionId",
                   "http://soacat.blogspot.com");

                if (pos >= 0)
                {
                     return OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(pos);
                }
                else
                {
                     return string.Empty;
                }

            }



Ara ja només ens falta, poder enviar missatges al client des del negoci. Els requisits mínims són la url del servei de
missatgeria i el nom del Hub que contés les operacions de missatgeria. Un cop fet això, en el constructor del servei,
inicialitzen la connexió i el Hub.



      public class Orders: IOrders
        {
            private string _urlserver = "http://localhost:15560/";
            private string _hubname = "BusinessMessenger";
            private IHubConnection _hubconnection = null;
            private IHubProxy _hubproxy = null;

            public Orders()
            {
                _hubconnection = new HubConnection(_urlserver);
                _hubproxy = ((HubConnection)_hubconnection).CreateHubProxy(_hubname);

                // Engeguem la connexió i el HUB
                StartConnection();

            }

            private void StartConnection()
            {
                ((HubConnection)_hubconnection).Start().ContinueWith(task =>
                {
                    if (task.IsFaulted)
                    {
                        throw new FaultException<Exception>(task.Exception.GetBaseException());
                    }
                  }).Wait();
            }
...
SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ;
Ara creem dues funcions per enviar missatges cap el client utilitzant el hub.

       private void SendMessageToClient(string clientConnectionId, string message)
        {
            if(_hubconnection.State== Microsoft.AspNet.SignalR.Client.ConnectionState.Connected)
                if(!string.IsNullOrEmpty(clientConnectionId))
                    _hubproxy.Invoke("SendTo", clientConnectionId, message).Wait();
        }
        private void SendMessageToAllClient(string message)
        {
            if (_hubconnection.State == Microsoft.AspNet.SignalR.Client.ConnectionState.Connected)
                _hubproxy.Invoke("BroadCast", message);
        }




I ja està, la resta al Codi Font : https://dl.dropbox.com/u/108938215/WCF_SignalR/SolutionWCF_SignalR.rar



Veure Video 2 : http://youtu.be/_X5klFffnsU

More Related Content

Viewers also liked

Rock cycle
Rock cycleRock cycle
Rock cycle
Vance Kite
 
Briefing notes: CloudVelocity
Briefing notes:   CloudVelocityBriefing notes:   CloudVelocity
Briefing notes: CloudVelocity
Rishidot Research
 
Mozambique, africa
Mozambique, africaMozambique, africa
Mozambique, africa
anfromcreative
 
Magistri presentatsioon sander kaus
Magistri presentatsioon   sander kausMagistri presentatsioon   sander kaus
Magistri presentatsioon sander kausSander Kaus
 
Applying Tiered Linking - Tier 2
Applying Tiered Linking - Tier 2 Applying Tiered Linking - Tier 2
Applying Tiered Linking - Tier 2 sarahmaeh
 
Webdesign Seminar - Haal meer uit je website
Webdesign Seminar - Haal meer uit je websiteWebdesign Seminar - Haal meer uit je website
Webdesign Seminar - Haal meer uit je websiteWieger Waardenburg
 
Mcm 354 google presentation edited
Mcm 354  google presentation editedMcm 354  google presentation edited
Mcm 354 google presentation edited
r_aida
 
Merb Core
Merb CoreMerb Core

Viewers also liked (8)

Rock cycle
Rock cycleRock cycle
Rock cycle
 
Briefing notes: CloudVelocity
Briefing notes:   CloudVelocityBriefing notes:   CloudVelocity
Briefing notes: CloudVelocity
 
Mozambique, africa
Mozambique, africaMozambique, africa
Mozambique, africa
 
Magistri presentatsioon sander kaus
Magistri presentatsioon   sander kausMagistri presentatsioon   sander kaus
Magistri presentatsioon sander kaus
 
Applying Tiered Linking - Tier 2
Applying Tiered Linking - Tier 2 Applying Tiered Linking - Tier 2
Applying Tiered Linking - Tier 2
 
Webdesign Seminar - Haal meer uit je website
Webdesign Seminar - Haal meer uit je websiteWebdesign Seminar - Haal meer uit je website
Webdesign Seminar - Haal meer uit je website
 
Mcm 354 google presentation edited
Mcm 354  google presentation editedMcm 354  google presentation edited
Mcm 354 google presentation edited
 
Merb Core
Merb CoreMerb Core
Merb Core
 

Similar to Wcf i signalR : Business Feedback

Sync toasync
Sync toasyncSync toasync
Sync toasync
jcastellsg
 
Presentació Ajax
Presentació AjaxPresentació Ajax
Presentació Ajax
Roger Casadejús Pérez
 
Programació Web - PAC 4 - Multimèdia (UOC) - Paquita Ribas
Programació  Web - PAC 4 - Multimèdia (UOC) - Paquita RibasProgramació  Web - PAC 4 - Multimèdia (UOC) - Paquita Ribas
Programació Web - PAC 4 - Multimèdia (UOC) - Paquita Ribas
Paquita Ribas
 
Programació Web - PAC 4 correcció - Multimèdia (UOC) - Paquita Ribas
Programació  Web - PAC 4 correcció - Multimèdia (UOC) - Paquita RibasProgramació  Web - PAC 4 correcció - Multimèdia (UOC) - Paquita Ribas
Programació Web - PAC 4 correcció - Multimèdia (UOC) - Paquita Ribas
Paquita Ribas
 
Aplicacions Interactives multiplataforma_pac3
Aplicacions Interactives multiplataforma_pac3Aplicacions Interactives multiplataforma_pac3
Aplicacions Interactives multiplataforma_pac3
Marcos Baldovi
 
Programem la placa Arduino - Presentación para la asignatura de robótica
Programem la placa Arduino - Presentación para la asignatura de robóticaProgramem la placa Arduino - Presentación para la asignatura de robótica
Programem la placa Arduino - Presentación para la asignatura de robótica
emunoz341
 
PW_pac1
PW_pac1PW_pac1
Programació Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació  Web - PAC 2 correcció - Multimèdia (UOC) - Paquita RibasProgramació  Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Paquita Ribas
 
Practica
PracticaPractica
Practica
Marcos Baldovi
 

Similar to Wcf i signalR : Business Feedback (9)

Sync toasync
Sync toasyncSync toasync
Sync toasync
 
Presentació Ajax
Presentació AjaxPresentació Ajax
Presentació Ajax
 
Programació Web - PAC 4 - Multimèdia (UOC) - Paquita Ribas
Programació  Web - PAC 4 - Multimèdia (UOC) - Paquita RibasProgramació  Web - PAC 4 - Multimèdia (UOC) - Paquita Ribas
Programació Web - PAC 4 - Multimèdia (UOC) - Paquita Ribas
 
Programació Web - PAC 4 correcció - Multimèdia (UOC) - Paquita Ribas
Programació  Web - PAC 4 correcció - Multimèdia (UOC) - Paquita RibasProgramació  Web - PAC 4 correcció - Multimèdia (UOC) - Paquita Ribas
Programació Web - PAC 4 correcció - Multimèdia (UOC) - Paquita Ribas
 
Aplicacions Interactives multiplataforma_pac3
Aplicacions Interactives multiplataforma_pac3Aplicacions Interactives multiplataforma_pac3
Aplicacions Interactives multiplataforma_pac3
 
Programem la placa Arduino - Presentación para la asignatura de robótica
Programem la placa Arduino - Presentación para la asignatura de robóticaProgramem la placa Arduino - Presentación para la asignatura de robótica
Programem la placa Arduino - Presentación para la asignatura de robótica
 
PW_pac1
PW_pac1PW_pac1
PW_pac1
 
Programació Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació  Web - PAC 2 correcció - Multimèdia (UOC) - Paquita RibasProgramació  Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
Programació Web - PAC 2 correcció - Multimèdia (UOC) - Paquita Ribas
 
Practica
PracticaPractica
Practica
 

Wcf i signalR : Business Feedback

  • 1. SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ; WCF i SignalR La idea és aconseguir que un servei WCF on podem tenir allotjades les operacions de negoci d’una aplicació, pugui donar un feedback del que està fent en temps real a l’usuari de l’aplicació. Per poder fer això de manera molt fàcil, utilitzaré el VS2012 Professional, el Framework 4.5, i dues llibreries RC, Microsoft ASP.NET SignalR SystemWeb i Microsoft ASP.NET SignalR Client.
  • 2. SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ; Partirem de que tenim una aplicació client “activa”, en el meu cas i com a exemple, feta amb Winforms, que es connecta a un servei que té operacions de negoci fet amb WCF. Ara doncs es tracta d’aprofitar la potencia de SignalR per poder fer que el servidor sigui capaç d’informar al client del que està passat en el procés de negoci invocat. Primer de tot, crearem el servidor de missatges. 1. Crear un projecte Web buit. 2. Afegir refèrencia a Microsoft ASP.NET SignalR SystemWeb amb Nuget. 3. Afegir Global.asax. 4. Crear un Hub, amb les operacions que invocarem, i en la seva implementació i posarem les operacions dinàmiques que subscriuran els clients. Mirar video1: http://youtu.be/g0JiRbpK0l8 Un cop tenim el servidor de missatges “SRServer”, preparem el servei de negoci i l’aplicació client per poder treballar com a clients del servei de missatgeria. En aquest cas, l’ aplicació client només escoltarà, o ben dit, rebrà missatges i el servei n’enviarà. Això no vol dir que no puguin fer les dues feines els dos. A ambdós projectes li afegim la llibreria i Microsoft ASP.NET SignalR Client, amb Nuget package manager. Un cop fet això implementarem les subscripcions del client winforms. En el codi del form1 i declarem unes variables: private string urlmessenger = "http://localhost:15560/"; private string hubproxy = "BusinessMessenger"; HubConnection hubConnection = null; Sobreescrivim el delegat de l’event “OnShown”: protected override void OnShown(EventArgs e) { base.OnShown(e); hubConnection = new HubConnection(urlmessenger); //Creem el proxy var messageHub = hubConnection.CreateHubProxy(hubproxy); var schu = TaskScheduler.FromCurrentSynchronizationContext(); // ens subscrivim als metodes dinàmics del servidor messageHub.On<string>("sendmessage", message => { // do our work on the UI thread Task.Factory.StartNew( () => { this.textBoxConsole.ForeColor = Color.White; this.textBoxConsole.AppendText(message + Environment.NewLine); }, CancellationToken.None, TaskCreationOptions.None, schu ); }); messageHub.On<string>("sendBCmessage", message => { // do our work on the UI thread
  • 3. SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ; Task.Factory.StartNew( () => { this.textBoxConsole.ForeColor = Color.Yellow; this.textBoxConsole.AppendText(message + Environment.NewLine); }, CancellationToken.None, TaskCreationOptions.None, schu ); }); hubConnection.Start().ContinueWith(task => { if (task.IsFaulted) { task.ContinueWith((result) => { textBoxConsole.ForeColor = Color.Red; textBoxConsole.AppendText( String.Format("Hi ha un error obrint la conexió: {0}{1}", result.Exception.GetBaseException(), Environment.NewLine)); } , schu); } else { task.ContinueWith((result) => { textBoxConsole.ForeColor = Color.Green; textBoxConsole.AppendText( String.Format("La conexió s'ha obert correctament -ConnectionId:[{0}]-{1}", hubConnection.ConnectionId, Environment.NewLine)); }, schu); } }).Wait(); EnableControls(); } private void EnableControls() { this.button1.Enabled = true; this.button2.Enabled = true; this.textBoxConsole.Enabled = true; } Un cop fet això ja tenim el client subscrit a dos funcions del servidor per rebre missatges.
  • 4. SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ; Si ens hi fixem tenim un identificador de connexió. Aquest és el que haurà de fer servir el servei en la instància que serveix en cada moment al client. I per tant d’alguna manera hem de passar-lo al servei. Com que els serveis podem utilitzar-los de moltes maneres, amb sessions, sense, podem passar sempre per paràmetre l ‘id de connexió, ..., bé, pensem. Si el passem com a paràmetre, hauríem de modificar totes les operacions de la interfície que voléssim que enviéssim missatges, i si el client ja el tenim implementat, modificar totes les crides a aquestes operacions. Imaginem-nos que en tenim moltes, quin rotllo. I imaginem que moltes aplicacions accedeixen a operacions del servei de negoci, BUA!!!!!. I el codi que picarem no el podrem reutilitzar......pensem. Bé, si no volem fer res de tot això, i volem que sempre passi el id cap al servei, independentment de com està instanciat, si permet sessions o no, i de com tracta la concurrència, la millor manera es mitjançant un paràmetre de capçalera. Si nosaltres som capaços de modificar la connexió client de tal manera que a cada crida d’operació li afegim una capçalera amb el id de connexió, i a les operacions del servei que vulguin enviar un missatge al client, puguin obtenir el id de connexió d’aquest, ja ho tenim solucionat. Per fer-ho ens creem una classe que implementarà dues interfícies del namespace System.ServiceModel.Dispacher i System.ServideModel.Description. I en el mètode BeforeSendRequest modificarem la capçalera del missatge. I després, quan creem la connexió li afegirem aquesta classe com a nou comportament del client. public class WcfClientInspector : IClientMessageInspector, IEndpointBehavior { static string _namespace = "http://soacat.blogspot.com"; private string _messengerConnectionId = string.Empty; public WcfClientInspector(string messengerConnectionId) { _messengerConnectionId = messengerConnectionId; } public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) { } public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) { MessageHeader<string> header = new MessageHeader<string>(_messengerConnectionId); request.Headers.Add(header.GetUntypedHeader("MessengerConnectionId", _namespace)); return null; } public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(this); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
  • 5. SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ; public void Validate(ServiceEndpoint endpoint) { } } Ara modifiquem els delegats dels events del botons per tal de que invoquin les operacions del servei, afegint el comportament nou. private async void button1_Click(object sender, EventArgs e) { button1.Enabled = false; RefOrderService.IOrders cliordres = CreateAndOpenClient(); await cliordres.ProcessOrdersAsync().ContinueWith((r)=>{ CloseClient((ICommunicationObject)cliordres); button1.Enabled = true; }, TaskScheduler.FromCurrentSynchronizationContext()); } private async void button2_Click(object sender, EventArgs e) { button2.Enabled = false; RefOrderService.IOrders cliordres = CreateAndOpenClient(); await cliordres.MailingAsync().ContinueWith((s) => { textBoxConsole.ForeColor = Color.Blue; textBoxConsole.AppendText(string.Format("{0}-{1}", s.Result, Environment.NewLine)); this.textBoxConsole.SelectionStart = this.textBoxConsole.Text.Length; this.textBoxConsole.ScrollToCaret(); CloseClient((ICommunicationObject)cliordres); button2.Enabled = true; }, TaskScheduler.FromCurrentSynchronizationContext()); } private RefOrderService.IOrders CreateAndOpenClient() { RefOrderService.OrdersClient client = new RefOrderService.OrdersClient(); client.Endpoint.EndpointBehaviors.Add(new WcfClientInspector(hubConnection.ConnectionId)); client.Open(); return client; } private void CloseClient(ICommunicationObject comobj){ comobj.Close(); } Ara ja només ens falta el servei de negoci. Primer haurà de poder recuperar la el id de connexió del client cap el servei de missatges, i després saber com enviar-li un missatge. Farem una funció senzilla al servei, que llegira la capçalera requerida.
  • 6. SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ; private string GetClientMessengerConnectionId() { int pos=OperationContext.Current. IncomingMessageHeaders.FindHeader("MessengerConnectionId", "http://soacat.blogspot.com"); if (pos >= 0) { return OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(pos); } else { return string.Empty; } } Ara ja només ens falta, poder enviar missatges al client des del negoci. Els requisits mínims són la url del servei de missatgeria i el nom del Hub que contés les operacions de missatgeria. Un cop fet això, en el constructor del servei, inicialitzen la connexió i el Hub. public class Orders: IOrders { private string _urlserver = "http://localhost:15560/"; private string _hubname = "BusinessMessenger"; private IHubConnection _hubconnection = null; private IHubProxy _hubproxy = null; public Orders() { _hubconnection = new HubConnection(_urlserver); _hubproxy = ((HubConnection)_hubconnection).CreateHubProxy(_hubname); // Engeguem la connexió i el HUB StartConnection(); } private void StartConnection() { ((HubConnection)_hubconnection).Start().ContinueWith(task => { if (task.IsFaulted) { throw new FaultException<Exception>(task.Exception.GetBaseException()); } }).Wait(); } ...
  • 7. SOACat: http://soacat.blogspot.com ; https://twitter.com/SOACAT ; Ara creem dues funcions per enviar missatges cap el client utilitzant el hub. private void SendMessageToClient(string clientConnectionId, string message) { if(_hubconnection.State== Microsoft.AspNet.SignalR.Client.ConnectionState.Connected) if(!string.IsNullOrEmpty(clientConnectionId)) _hubproxy.Invoke("SendTo", clientConnectionId, message).Wait(); } private void SendMessageToAllClient(string message) { if (_hubconnection.State == Microsoft.AspNet.SignalR.Client.ConnectionState.Connected) _hubproxy.Invoke("BroadCast", message); } I ja està, la resta al Codi Font : https://dl.dropbox.com/u/108938215/WCF_SignalR/SolutionWCF_SignalR.rar Veure Video 2 : http://youtu.be/_X5klFffnsU