Developing Async apps using WCF and MSMQ -- Part 1

by Hari Mukkapati 30. June 2009 17:38

Software Requirements

  • Visual Studio 2008  (Also works in 2005, but not tested for this tutorial.)
  • MSMQ Installed and Running.  To Implement Security MSMQ installation must be integrated to AD.
  • .NET 3.0 Framework or higher
  • IIS
  • Distributed Transaction Coordinator (DTC) Must be installed and running.

The Goal here is to setup an asynchronous communication between a client and server using WCF and MSMQ.  To do that I use a “WCFQ” solution which contains 3 projects.

The Goal here is to setup an asynchronous communication between a client and server using WCF and MSMQ.  To do that I use a “WCFQ” solution which contains 3 projects. 

  • WCFQ.Service – Hosts Queued WCF Service.
  • WCFQ.Contract – Contains the Data and Service contracts for the Queued WCF Service.
  • WCFQ.Client – A Console application to call WCFQ.Service

 

Step 1:  Open Visual Studio 2008 IDE and Create a “WCF Service Application”

 

image001 

 

 

Step 2: Add another “Class Library” Project and Delete “Class1.cs” from the project.

 

Step 3: Delete IService1.cs in WCFQ.Service and add IService1.cs to WCFQ.Contract and replace the code with below.  The trick here is when building WCF-MSMQ services is to ensure that all the operation contracts are defined with IsOneWay=true.

using System; 
using System.Runtime.Serialization; 
using System.ServiceModel; 

namespace WCFQ.Contract 
{ 
    [ServiceContract] 
    public interface IService1 
    { 
        [OperationContract(IsOneWay=true)] 
        void SendData(QData composite); 
    } 

    //An object for Data Contract 
    [DataContract] 
    public class QData 
    { 
        [DataMember] 
        public string Name { get; set; } 
    } 
}
 

Step 4: Add references of “System.ServiceModel” and “System.Runtime.Serialization” to WCFQ.Contract. This is where you define the contract.

Step 5: Reference WCFQ.Contract project in WCFQ.Service and change the Service1.svc.cs code should look like this.

using System; 
using System.Diagnostics; 
using WCFQ.Contract; 
namespace WCFQ.Service 
{ 
    public class Service1 : IService1 
    { 
        public void SendData(QData qdata) 
        { 
            //Do something with the data 
            Trace.WriteLine(String.Format("Name : {0}", qdata.Name)); 
        } 
    } 
}

Step 6: Now, The configuration comes into picture. Here is how the ServiceModel part of web.config should look like. We don’t need wsHttpBinding to get net MSMQ to be working.  That is default and I left it that way to make it easy to understand the WCF Service is working.

<SYSTEM.SERVICEMODEL>
    <BINDINGS>
        <NETMSMQBINDING>
            <BINDING name="WCFQNonTransactional" exactlyonce="false">
                <SECURITY mode="None" />
            </BINDING>
        </NETMSMQBINDING>
    </BINDINGS>
    <SERVICES>
        <SERVICE name="WCFQ.Service.Service1" behaviorconfiguration="WCFQ.Service.Service1Behavior">
            <ENDPOINT contract="WCFQ.Contract.IService1" binding="wsHttpBinding" address="http://localhost/WCFQService/Service1.svc">
                <IDENTITY>
                    <DNS value="localhost" />
                </IDENTITY>
            </ENDPOINT>
            <ENDPOINT contract="WCFQ.Contract.IService1" binding="netMsmqBinding" address="net.msmq://localhost/private/WCFQService/Service1.svc" bindingconfiguration="WCFQNonTransactional" />
        </SERVICE>
    </SERVICES>
    <BEHAVIORS>
        <SERVICEBEHAVIORS>
            <BEHAVIOR name="WCFQ.Service.Service1Behavior">
                <SERVICEMETADATA httpgetenabled="true" />
                <SERVICEDEBUG includeexceptiondetailinfaults="false" />
            </BEHAVIOR>
        </SERVICEBEHAVIORS>
    </BEHAVIORS>
</SYSTEM.SERVICEMODEL>

Step 7:  The WCF service to work with MSMQ there is one more rule. That is the queue name which must be same as the URI that is used to Access the WCF Service. So, if the URL is http://localhost/WCFQService/Service1.svc, then the Queue Name will be “WCFQService/Service1.svc”. This has to be created manually by going to “Computer Management/Services and Applications/Message Queuing/Private Queues”.  When creating the Queue, Do not check “Transactional”. Computer Management can be accessed from Right click on My Computer and click on Manage or “Start -> Run” and typing “Compmgmt.msc” and Hit enter.

 image002 

Step 8: After creating the queue, enable Journal by Right click and select properties on the queue. Check the Enabled checkbox inside Journal Area. This is just for tracking purpose that your messages reached MSMQ. Next go to security tab of the properties and Add user “Network Service” and give full control to the user. This is the user who writes and reads out messages from the queue.

 

image003 

 

image004 

Step 9: Configure the WCFQ.Service to Run in IIS by setting the project properties. Remove the DOT from the WCFQ.Service and Create virtual directory. [Note: Windows 7 or Windows 2008 server must create an application pool which runs with “Network service” User, instead of “ApplicationPoolIdentity” and assign the application pool create to the WCFQService from IIS, INetMgr]

 

 image005

 

Step 10:  In order to make the WCF to work with MSMQ we need to enable MSMQ WAS listener on the WCFQService application that is just created by running following command from command prompt from location C:\Windows\System32\inetsrv.

appcmd set app "Default web site/WCFQService" /enabledProtocols:net.msmq,http

 

 image006

 

This enables the net.msmq protocol on WCFQService application on IIS.

Step 11: Now, The WCFQService application is ready to roll. So, let’s get to the client. Add a Console Application to the project.  And add references for WCFQ.Contract project, System.ServiceModel.

Step 12: Without having to create a proxy and access the WCF service, Add a new class called “WCFQService1Client.cs”. The proxy class derives from the class ClientBase<T>. ClientBase<T> accepts a single generic type parameter identifying the service contract that this proxy encapsulates. The Channel property of ClientBase<T> is of the type of that type parameter. The generated subclass of ClientBase<T> simply delegates to Channel the method call.

using System; 
using System.ServiceModel; 
using WCFQ.Contract; 

namespace WCFQ.Client 
{ 
    internal class WCFQService1Client : ClientBase, IService1 
    { 
        public WCFQService1Client(string endpoint) : base(endpoint) 
        { 

        } 

        //IService1 Members 
        public void SendData(QData data) 
        { 
            Channel.SendData(data); 
        } 
    } 
}

Step 13: Now configure the Client app.config to access the WCF Service.

<?xml version="1.0" encoding="utf-8"?>
<CONFIGURATION>
    <SYSTEM.SERVICEMODEL>
        <BINDINGS>
            <NETMSMQBINDING>
                <BINDING name="WCFQNonTransactional" exactlyonce="false">
                    <SECURITY mode="None" />
                </BINDING>
            </NETMSMQBINDING>
            <WSHTTPBINDING>
                <BINDING name="WCFQwsHttp">
                    <SECURITY mode="None" />
                </BINDING>
            </WSHTTPBINDING>
        </BINDINGS>
        <CLIENT>
            <ENDPOINT name="WCFQNonTransactional" contract="WCFQ.Contract.IService1" binding="netMsmqBinding" address="net.msmq://localhost/private/WCFQService/Service1.svc" bindingconfiguration="WCFQNonTransactional" />
            <ENDPOINT name="WCFQwsHttp" contract="WCFQ.Contract.IService1" binding="wsHttpBinding" address="http://localhost/WCFQService/Service1.svc" bindingconfiguration="WCFQwsHttp" />
        </CLIENT>
    </SYSTEM.SERVICEMODEL>
</CONFIGURATION>

 

Step 13: To use the proxy, the client first needs to instantiate a proxy object and provide the constructor with endpoint information from the endpoint section name from the config file. The client can then use the proxy methods to call the service, and when the client is done, the client needs to close the proxy instance. The program.cs will look like this after implementing the code.

using System; 
using WCFQ.Contract; 

namespace WCFQ.Client 
{ 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            QData data = new QData(); 
            data.Message = "Hello World!";            

            //Send Message 
            using (WCFQService1Client proxy = new WCFQService1Client("WCFQNonTransactional")) 
            { 
                Console.WriteLine("Sending Message {0} ", data.Message); 
                proxy.SendData(data); 

                //Close the client. 
                proxy.Close(); 

            }//Dispose 
            
            Console.Read(); 
        } 
    } 
}

Step 14: Set WCFQ.Client as the startup project and run……. Here is what needs to be observed to make sure the service and client ran fine.

Command window of client will show

image007 

MSMQ Window will show the journal message count increased by 1.

image008


    Next time I will post on working with transactional messaging.

Click hear to Download source code here…

Tags: , , , ,

Mukkapati.com

About the author

Hari Mukkapati

Month List

Calendar

<<  June 2009  >>
MoTuWeThFrSaSu
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

View posts in large calendar