Click here to Skip to main content
15,885,366 members
Articles / Programming Languages / C# 4.0

Wcf Client Server Push using MSMQ

Rate me:
Please Sign up or sign in to vote.
4.88/5 (6 votes)
8 Feb 2011CPOL3 min read 58.7K   2.2K   35   9
Client Server internal push technology using MSMQ and WCF

Introduction

Searching for an easy solution for server push technology using WCF was a bit of a hassle.

I had few requirements:

  1. Must use WCF
  2. Both the server and the client applications don't have to run while messages were being transmitted
  3. A common Queue for all the clients on the server side
  4. Server push is required - can't use polling

IIS WebService was an option but was complicated to implement with a common client Queue.

A solution was found using Microsoft Message Queuing system. Both the client and the server have a message box that use to communicate. Both applications don't have to run while messaging the opposite side.

Note

This project is not done to explain bindings, contracts and services. This is done to provide a simple server push design overview.

Requirements

  1. MSMQ installed (server and clients) - Go to Control Panel -> Add Remove Program -> Add Windows Component and select “Message Queuing”
  2. Run Visual Studio as administrator.
  3. Client and Server must be able to see each other (ping each other using either IP or host name). If you need external communication support - see the "Modification for public communication" section.

Overview

Modification for Public Communication

If a WebService is required - for external internet communication, a wrapper can be made which provides a WebService endpoint and creates an internal Queue message. This will remove the requirement for both client and server to see each other's messaging queue.

Using the Code

The flow is as follows:

Client registers itself by giving the server its own MSMQ address.

C#
RegisterClientServiceClient registerClientServiceClient = 
		new RegisterClientServiceClient("RegisterClientEndPoint");

using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
	ClientInfo clientInfo = new ClientInfo();

	clientInfo.GroupName = ConfigurationManager.AppSettings["GroupName"];
	clientInfo.ClientName = System.Net.Dns.GetHostName();

	// ClientName can be changed to ip address
	clientInfo.PushMessageBoxAddress = "net.msmq://" + 
		clientInfo.ClientName + "/private/WcfServerPush/ClientMessageBox";

	registerClientServiceClient.RegisterClient(clientInfo);
				
	scope.Complete();
}   

RegisterClientServiceClient class derives from the RegisterClientIService and using the ClientBase template. This is regular WCF implementation.

C#
 public class RegisterClientServiceClient : 
	ClientBase<RegisterClientIService>, RegisterClientIService
{
	public RegisterClientServiceClient(string endpointConfigurationName) :
		base(endpointConfigurationName)
	{
	}

	public void RegisterClient(ClientInfo clientInfo)
	{
		base.Channel.RegisterClient(clientInfo);
	}
}  

On the server side, RegisterClient is implemented as a regular operation which derives from the same interface service RegisterClientIService:

C#
public class RegisterClientService : RegisterClientIService
{
	[OperationBehavior(TransactionScopeRequired = 
			true, TransactionAutoComplete = true)]
	public void RegisterClient(ClientInfo clientInfo)
	{
		WcfServerPushServerBO.Instance.RegisterClient(clientInfo);
	}
}

Creating the MSMQ ServiceHost on the server side is easy:

C#
 if (!MessageQueue.Exists(registerClientMSMQName))
{
	MessageQueue versionManagerQueue = 
		MessageQueue.Create(registerClientMSMQName, true);
	versionManagerQueue.SetPermissions
		(@"Everyone", MessageQueueAccessRights.FullControl);

	versionManagerQueue.SetPermissions(@"ANONYMOUS LOGON",
		MessageQueueAccessRights.ReceiveMessage |
		MessageQueueAccessRights.PeekMessage |
		MessageQueueAccessRights.WriteMessage);
}   

The client side is almost the same as the server side, but with a small modification. Because we want the ability for the WPF to register an event with the ServiceHost - whenever we get a new message, we need to create the actual service and give its instance to the ServiceHost. Whenever we provide an instance of a service to the ServiceHost, we must add an InstanceConextMode.Single to the behavior:

C#
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class PushMessageService : MessageBoxIService, INotifyPropertyChanged 

Lastly, we need to modify the App.Config to define the Service. We can also give an http binding (not only the netMsmqBinding) to the endpoint - if in the future we would like to provide a metadata exchange ability.

XML
 <service name="WcfServerPushServer.RegisterClientService" 
	behaviorConfiguration="WcfServerPushServer.RegisterClientServiceBehavior">
  <host>
	  <baseAddresses>
	  <add baseAddress="http://localhost:8001/WcfServerPush/
				RegisterClientServiceHttp/" />
	  </baseAddresses>
  </host>

  <endpoint address="net.msmq://localhost/private/WcfServerPush/RegisterClientService"
			  binding="netMsmqBinding"
			  bindingConfiguration="srmpBinding"
			  contract="WcfServerPushIServices.RegisterClientIService">
  </endpoint>
  <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service> 

The client side needs to recognize the endpoint as follows:

XML
<client>
	<endpoint name="RegisterClientEndPoint" 
	address="net.msmq://localhost/private/WcfServerPush/RegisterClientService" 
	binding="netMsmqBinding" bindingConfiguration="netMsmqBindingConfig" 
	contract="WcfServerPushIServices.RegisterClientIService"/>
</client> 

Solution Architecture

  • WcfServerPush - A WPF project that serves as both the client and server application. You can install the application on either side and decide yourself what to run. The WPF project is also responsible to create the message queue if not found and start the service hosts. In a real development project - it is important to separate the view from the boot bootstrapper.
  • WcfServerPushServer - The server side service and business objects, including the client's Queue
  • WcfServerPushClient - The client side service
  • WcfServerPushIServices - The message box service interface and the register client service interface. Common project for both the server and the client.

History

  • February 6th 2011: First release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Mehul M Thakkar10-Apr-15 2:33
Mehul M Thakkar10-Apr-15 2:33 
QuestionCan I use it over internet? Pin
Mehul M Thakkar10-Apr-15 2:32
Mehul M Thakkar10-Apr-15 2:32 
QuestionWhere is the overview image Pin
Stef.Moser24-Apr-12 21:21
Stef.Moser24-Apr-12 21:21 
AnswerRe: Where is the overview image Pin
Gil Zhaiek25-Apr-12 8:07
Gil Zhaiek25-Apr-12 8:07 
QuestionNeed Help? Pin
Member 774102317-Mar-11 0:44
Member 774102317-Mar-11 0:44 
GeneralMy vote of 5 Pin
Burak Ozdiken14-Feb-11 12:57
Burak Ozdiken14-Feb-11 12:57 
GeneralRe: My vote of 5 Pin
Gil Zhaiek15-Feb-11 7:32
Gil Zhaiek15-Feb-11 7:32 
Generalnice - have 5 Pin
Pranay Rana7-Feb-11 2:04
professionalPranay Rana7-Feb-11 2:04 
GeneralRe: nice - have 5 Pin
Gil Zhaiek7-Feb-11 5:44
Gil Zhaiek7-Feb-11 5:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.