Saturday, 28 January 2012

Events

Events allow the client or clients to be notified about something that has occurred on the service side. An event may result from a direct client call, or it may be the result of something the service monitors. The service firing the event is called the publisher, and the client receiving the event is called the subscriber.


  • Publisher will not care about order of invocation of subscriber. Subscriber can be executed in any manner.
  • Implementation of subscriber side should be short duration. Let us consider the scenario in which you what to publish large volume of event. Publisher will be blocked, when subscriber is queued on previous subscription of the event. These make publishers to put in wait state. It may lead Publisher event not to reach other subscriber.
  • Large number of subscribers to the event makes the accumulated processing time of each subscriber could exceed the publisher's timeout
  • Managing the list of subscribers and their preferences is a completely service-side implementation. It will not affect the client; publisher can even use .Net delegates to manage the list of subscribers.
  • Event should always one-Way operation and it should not return any value

Definition

    public interface IMyEvents
    {
        [OperationContract(IsOneWay = true)]
        void Event1();
    }
Let us understand more on Event operation by creating sample service
Step 1 : Create ClassLibrary project in the Visual Studio 2008 and name it as WCFEventService as shown below.
Step 2: Add reference System.ServiceModel to the project
Create the Event operation at the service and set IsOnwWay property to true. This operation should not return any value. Since service has to communicate to the client, we need to use CallbackContract for duplex communication. Here we are using one operation to subscribe the event and another for firing the event.
public interface IMyEvents
    {
        [OperationContract(IsOneWay = true)]
        void Event1();
    }

   [ServiceContract(CallbackContract = typeof(IMyEvents))]
   public interface IMyContract
   {
       [OperationContract]
       void DoSomethingAndFireEvent();

       [OperationContract]
       void SubscribeEvent();

   }
Step 3: Implementation of the Service Contract is shown below.
In the Subscription operation, I am using Operationcontext to get the reference to the client instance and Subscription method is added as event handler to the service event. DoSomethingAndFireEvent operation will fire the event as shown.
MyPublisher.cs
   [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
   public  class MyPublisher : IMyContract
    {
        static Action m_Event1 = delegate { };

        public void SubscribeEvent()
        {
            IMyEvents subscriber = OperationContext.Current.GetCallbackChannel();
            m_Event1 += subscriber.Event1;
        }

        public static void FireEvent()
        {
            m_Event1();
        }

        public void DoSomethingAndFireEvent()
        {
            MyPublisher.FireEvent();           
        }
    }
Step 4: Create the Console application using Visual Studio 2008 and name it as WcfEventServiceHost. This application will be used to self-host the service.
Step 5: Add System.ServiceModel and WcfEventService as reference to the project.
static void Main(string[] args)
        {
            Uri httpUrl = new Uri("http://localhost:8090/MyPublisher/");
            ServiceHost host = new ServiceHost(typeof(WcfEventService.MyPublisher), httpUrl);
            host.Open();
            Console.WriteLine("Service is Hosted at {0}", DateTime.Now.ToString());
            Console.WriteLine("Host is running...Press  key to stop the service.");
            Console.ReadLine();
            host.Close();
        }
  
Step 6: Use Duplex binding to support Callback operation.
Web.Config
<system.serviceModel>
    <services >
      <service behaviorConfiguration="ServiceBehavior"  
      name="WcfEventService.MyPublisher">
        <endpoint address="http://localhost:8090/MyPublisher" 
        binding="wsDualHttpBinding" contract="WcfEventService.IMyContract">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding"
         contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true "/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
Step7: Run the host application as shown below.
Step 8: Create the console application using visual studio and name it as WcfEventServiceClient as shown below. This application will act a client which is used to subscribe the event from service.
Step 9: Create the proxy class as shown below. Use DuplexClientBase to create the proxy, because it will support bidirectional communication. Create the contractor which will accept InstanceContext as parameter.
EventServiceClient.cs
 class EventServiceClient:DuplexClientBase<IMyContract>,IMyContract 
    {
        public EventServiceClient(InstanceContext eventCntx)
            : base(eventCntx)
        {
            
        }

        public void  DoSomethingAndFireEvent()
        {
            base.Channel.DoSomethingAndFireEvent();
        }

        public void SubscribeEvent()
        {
            base.Channel.SubscribeEvent();
        }
      
    }
Step 10: Implementation of IMyEvents at client side is shown below. This method will be called when service publish the event.
class MySubscriber : IMyEvents
    {
       public void Event1()
        {
            Console.WriteLine("Event is subscribed from the 
            service at {0}",DateTime.Now.ToString() );
        }
  
    }
Step 11: Main method of the client side you can find the creating Subscription instance and it passed to service using InstanceContext
 static void Main(string[] args)
        {
            IMyEvents evnt = new MySubscriber();
            InstanceContext evntCntx = new InstanceContext(evnt);

            EventServiceClient proxy = new EventServiceClient(evntCntx);
            Console.WriteLine("Client subscribe the event
             from the service at {0}",DateTime.Now.ToString());
            proxy.SubscribeEvent();
            Console.WriteLine("Client call operation which will fire the event");
            proxy.DoSomethingAndFireEvent();
            Console.ReadLine();
        }
Step 12: Run the client application and you see the when event is fired from the service. Subscriber got notification.

No comments:

Post a Comment