Sunday, July 13, 2008

Bindings

Basics of Binding

All samples so far has been either on HTTP or TCP or both. We have a lot more of bindings available. Table below indicates a few of them

Types of Binding
  • BasicHttpBinding - When consumed by ASP.NET and other web services
  • WsHttpBinding - This conforms to WS standards which supports Reliable sessions, transaction and security. It also supports both HTTP and HTTPS protocols
  • WSDualHttpBinding - Similar to WsHttpBinding, supports Duplex communication
  • WSFederationBinding - Enables web services operating in different security realms to agree on common mechanism for identifying users
  • NetTcpBinding - TCP communication. Typically used in intranet solution. Messages are delivered using binary encoding
  • NetPeerTcpBinding - Peer to peer communication using TCP. Used only for intranet solutions. Messages are delivered using binary encoding
  • NetNamedPipeBinding - Used for High performance intranet and inter-process communication. This communication supports transactions, reliable sessions and high secure systems
  • NetMsmqBinding - MSMQ is used as transport to transmit messages between client and server. Thus binding supports reliable, secure and transaction operations

Service Interface

Let’s create a simple MsmqBinding solution.

This sample would host a simple service that would listen to clients for messages. Client would dispatch messages to MSMQ which would be picked in turn by server. This option allows client to send messages inspite of non-availability of server, which is not possible in any of the cases above NetMsmqBinding in the table. The same holds good for a server too

Here we take a dive into the code
Let’s start with a simple solution MSMQ Service.
  1. Create a WCF class library or a simple class library (then add reference to System.ServiceModel)
  2. Create a new file with the name IMSMQService.cs with the following contentsIMSMQService.cs
IMSMQService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace MSMQService
{
[ServiceContract(Namespace="http://techkrishnan.blogspot.com/2008/07/08", SessionMode=SessionMode.Required)]
interface IMSMQService
{
[OperationContract(IsInitiating=true, IsOneWay=true, IsTerminating=true)]
void SayHello(string sName);
}
}


As it is the only function in the service, I have set it to both initiate and terminate

Let’s now take a look at implementation of the service
This is a simple function. Program would involve to 2 transaction scopes. One in server side and other in client side. If any of them fail, transaction would have a faulty status, which would ensure message remains intact in MSMQ without any damage.

MSMQService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace MSMQService
{
public class MSMQService:IMSMQService
{
#region IMSMQService Members
[OperationBehavior(TransactionScopeRequired=true, TransactionAutoComplete=true)]
public void SayHello(string sName)
{
Console.WriteLine("Hello from {0} received at {1}", sName, DateTime.Now.ToString());
//return "Hello " + sName;
}
#endregion
}
}

Host Application

Let’s move on to our host application
This sample would look for the message queue defined in app.config. If not found it creates the message queue (in the private folder) and starts service. If messages are found in MSMQ then they are processed, else it waits for messages, until closed

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Messaging;
using System.Configuration;

namespace MSMQServiceHost
{
class Program
{
static void Main(string[] args)
{
using(ServiceHost sHost = new ServiceHost(typeof(MSMQService.MSMQService)))
{
string queueName = ConfigurationManager.AppSettings["queueName"];
try
{
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName, true);
sHost.Open();
Console.WriteLine("Service started in port 8000");
Console.WriteLine("Press any key to terminate service.....");
Console.ReadKey(true);
sHost.Close();
}
catch (Exception ex)
{
//sHost.Close();
Console.WriteLine("Exception occurred");
Console.WriteLine(ex.Message);
Console.WriteLine("\nInner Exception");
Console.WriteLine(ex.InnerException.Message.ToString());
}
}
}
}
}

App.config for host
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- Use appSetting to configure MSMQ queue name. -->
<add key="queueName" value=".\private$\SampleQueue" />
</appSettings>

<system.serviceModel>
<bindings>
<netMsmqBinding>
<binding name="MSMQServiceMSMQBinding">
<security>
<transport msmqAuthenticationMode="None" msmqProtectionLevel="None" />
</security>
</binding>
</netMsmqBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MSMQServiceHttpBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MSMQServiceHttpBehavior" name="MSMQService.MSMQService">
<clear />
<endpoint address="net.msmq://aa-09660/private/samplequeue"
binding="netMsmqBinding" bindingConfiguration="MSMQServiceMSMQBinding"
name="MSMQServiceMSMQEndPoint" contract="MSMQService.IMSMQService" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
name="MSMQServiceMex" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>

Client code

Let’s move on with client code
Proxy code for client should be generated before anything more is done in client side application
Client should create a reference for server and should invoke service from with a transaction scope.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Transactions;

namespace MSMQServiceClient
{
class Program
{
static void Main(string[] args)
{
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
MSMQServiceReference.MSMQServiceClient proxy = new MSMQServiceClient.MSMQServiceReference.MSMQServiceClient();
proxy.SayHello("Krishnan");
proxy.Close();
scope.Complete();
Console.WriteLine("Press any key to terminate.............");
Console.ReadKey(true);
}
}
}
}

Start the server and then start the client. You’ll see messages in server console. Now stop the server and start client normally with HTTP or TCP service clients, you’ll normally see an error. But in this case message would be sent to MSMQ. Now restart the server, you’ll see the message from MSMQ


Monday, July 7, 2008