MSMQ with WCF

Today I am going to show you how use Message Queuing (MSMQ) with Windows Communication Foundation (WCF). Message queue comes to show in different reasons like decoupling processes , ordering the process, handle bulk messages.

Writing an message into MSMQ is not a different, but processing the messages with effective ways is the challenge. As an example we had a problem which delay of sending emails and SMS from our side. Later when we were investigating the issue, we found that we were taking all messages and try to iterate at once.  This solution can be used to prevent kind of scenarios.

Hope you guys have installed the MSMQ before starting the development. So first create an empty solution and add two console projects. In my solution I have added three projects.

solution

 

  • Dto – contains data transfer objects
  • MSMQ – project used to write messages into message queue
  • WcfServer – read messages from message queue and process

 

Dto project contains this class.

[DataContract]
    public class User
    {
        public User()
        {
            
        }
        [DataMember(IsRequired = true)]
        public int UserId { get; set; }

        [DataMember(IsRequired = true)]
        public string FirstName { get; set; }

        [DataMember(IsRequired = false)]
        public string LastName { get; set; }

        [DataMember(IsRequired = true)]
        public string UserName { get; set; }

        [DataMember(IsRequired = true)]
        public string Email { get; set; }
    }

MSMQ project contains the code for write message into message queue

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;

namespace MSMQ
{
    class Program
    {
        
        static void Main(string[] args)
        {
            try
            {
                WriteToQueue();
            }
            catch (Exception ex)
            {
                throw ex;
            }
           
        }

        /// <summary>
        /// References : Thanks to below URLs
        /// http://www.dotnetcurry.com/wcf/1156/using-wcf-msmq-message-service-oriented-solutions
        /// 
        /// </summary>
        public static void WriteToQueue()
        {
            int i = 1;

            while (true)
            {
                Console.WriteLine("Creating new user");

                var user = new Dto.User()
                {
                    UserId = i,
                    FirstName = "Damith" + i,
                    LastName = "Wanninayake" + i,
                    Email = "damith.uwu@gmail.com",
                    UserName = "damith" + i
                };


                // Create a Message and set the body to the order object above
                var msmqPath = ConfigurationManager.AppSettings["MessageQueuePath"];
                var msg = new Message {Body = user};

                // Create a transaction
                using (var ts = new TransactionScope(TransactionScopeOption.Required))
                {
                    MessageQueue queue = null;

                    if (MessageQueue.Exists(msmqPath))
                    {
                        queue = new MessageQueue(msmqPath);
                    }
                    else
                    {
                        // Create transactional message queue
                        MessageQueue.Create(msmqPath, true);
                        queue = new MessageQueue(msmqPath);
                    }
                    queue.Send(user,"User registration",MessageQueueTransactionType.Automatic); // send the message
                    ts.Complete(); // complete the transaction
                }

                i += 1;
                Console.WriteLine("Message Sent");

                Thread.Sleep(5000);
            }
            
        }

    }
}

Here the app.config file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <appSettings>
    <add key="MessageQueuePath" value=".\Private$\EmailQueue"/>
      <!--<add key="MessageQueuePath" value="FormatName:Direct=TCP:127.0.0.1\private$\emailqueue"/>-->
    </appSettings>
</configuration>

Please be kind to adjust the code per your requirement. Here I want to add more and more messages into message queue quickly.

Run the project and see whether you have messages in your queue or not. Please see the below images of my queue.
write_console

queue

message

Now we have messages in out queue and need to read this messages. My requirement is when I receive a new message into queue, without looking into queue, automatically read method should be fired like a trigger.

I have a interface like below

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.MsmqIntegration;
using System.Text;
using System.Threading.Tasks;
using Dto;

namespace WcfServer.Interfaces
{
    [ServiceContract]
    [ServiceKnownType(typeof(User))]
    public interface IUserInboundMessageHandlerService
    {
        [OperationContract(IsOneWay = true, Action = "*")]
        void ProcessIncomingMessage(MsmqMessage incomingOrderMessage);
    }
}

and implemented class like below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.MsmqIntegration;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Dto;
using WcfServer.Interfaces;

namespace WcfServer
{
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single,
        ReleaseServiceInstanceOnTransactionComplete = false)]
    public class UserInboundMessageHandlerService : IUserInboundMessageHandlerService
    {
        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
        public void ProcessIncomingMessage(MsmqMessage<User> incomingOrderMessage)
        {
            Console.WriteLine("New Message Recieved.. Procession Output...");
            Console.WriteLine();
            var orderRequest = incomingOrderMessage.Body;
            Console.WriteLine(orderRequest.UserId);
            Console.WriteLine(orderRequest.FirstName);
            Console.WriteLine(orderRequest.LastName);
            Console.WriteLine(orderRequest.Email);
            Console.WriteLine(orderRequest.UserName);
            Console.WriteLine();
            Console.WriteLine("Procession completed...");

            //Thread.Sleep(1000);
        }
    }
}

Above method will be triggered from the MSMQ. But we have to create a Service host to run this wcf service since we are not using the IIS server.

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

namespace WcfServer
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(UserInboundMessageHandlerService));
            host.Faulted += host_Faulted;

            host.Open();
            Console.WriteLine("The service is ready");
            Console.WriteLine("Press  to terminate the service");
            Console.ReadLine();

            if (host != null)
            {
                if (host.State == CommunicationState.Faulted)
                {
                    host.Abort();
                }
                host.Close();
            }
        }

        static void host_Faulted(object sender, EventArgs e)
        {
            Console.WriteLine("Faulted!"); // Change to something more sensible – this is just an example showing what happens when the host has faulted.
        }
    }
}

Let’s see the config file which has end point and other configuarations.

  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="IncludeExceptionDetails">
          <callbackDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="WcfServer.UserInboundMessageHandlerService">
        <endpoint address="msmq.formatname:DIRECT=OS:.\private$\EmailQueue" binding="msmqIntegrationBinding" bindingConfiguration="IncomingMessageHandlerBinding" contract="WcfServer.Interfaces.IUserInboundMessageHandlerService">
        </endpoint>
      </service>
    </services>
    <bindings>
      <msmqIntegrationBinding>
        <binding name="IncomingMessageHandlerBinding"
                 closeTimeout="00:30:00"
                 receiveTimeout="01:00:00"
                 retryCycleDelay="00:00:10"
                 receiveRetryCount="0"
                 exactlyOnce="true"
                 maxRetryCycles="3"
                 receiveErrorHandling="Move">
          <security mode="None"/>
        </binding>
      </msmqIntegrationBinding>
    </bindings>
  </system.serviceModel>

All set. We need to run the application now.

final

You can adjust the thread sleep time and check the speed of the reading process.

You can download the code from here

https://github.com/uwudamith/MSMQ

 

Simple json editor using c#

editor

I have created a sample project to read json file, edit and save into another file using c# and Newtonsoft.Json library. If anyone want this kind of implementation, you can download project and continue. I have added the sample json file with the project into my Github repository.

Github repository

I have json file format like below.

{
"tasks": [{
"AccountName": "testaccount",
"AccountKey": "0de5edbc-6a02-4450-a139-33d4e760a257",
"ContainerName": "1234",
"RootPath": "/",
"DaysOfHistoryToKeep": 10
}, {
"AccountName": "test2",
"AccountKey": "f15c414b-734a-4a4e-b1a6-eb0794df4e46",
"ContainerName": "2345",
"RootPath": "/",
"DaysOfHistoryToKeep": 15
}]
}

According to that json structure, i am going to build my object structure like below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JsonEditor
{
    public class Task
    {
        public string AccountName { get; set; }
        public string AccountKey { get; set; }
        public string ContainerName { get; set; }
        public string RootPath { get; set; }
        public int DaysOfHistoryToKeep { get; set; }
    }
}

And I have Tasks class which contains list of Task classes.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JsonEditor
{
    public class Tasks
    {
        public List<Task> tasks { get; set; }
    }
}

This is how program going to read the json file and convert into list and bind into grid.

Stream myStream = null;
            OpenFileDialog theDialog = new OpenFileDialog();
            theDialog.Title = "Open Text File";
            theDialog.Filter = "JSON files|*.json";
            theDialog.InitialDirectory = @"C:\";
            if (theDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    if (theDialog.FileName.Trim() != string.Empty)
                    {
                        using (StreamReader r = new StreamReader(theDialog.FileName))
                        {
                            string json = r.ReadToEnd();
                            Tasks items = JsonConvert.DeserializeObject(json);
                            dgTasks.DataSource = items.tasks;
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }

And convert grid data into json file.

Tasks tasks = new Tasks();
            tasks.tasks = (List)dgTasks.DataSource;
            
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.InitialDirectory = @"C:\";
            saveFileDialog1.Filter = "JSON Image|*.json";
            saveFileDialog1.Title = "Save a JSON File";

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                File.WriteAllText(saveFileDialog1.FileName, JsonConvert.SerializeObject(tasks));
            }

Please download the project and use it in your projects. You have to add exception handling into this project.

How to extend c# ArrayList class

Sometimes we want to extend generic classes in c#. Here i have extended ArrayList in c# and overrided remove functions. I have also added Events to this class and if anyone interested you can go to my GitHub account and check.

Here is the extended class

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AnimalList
{

    // A delegate type for hooking up change notifications.
    //public delegate void MyAnimals_AnimalRemoved(MyAnimalList collection, Animal item);
    public delegate void MyAnimals_AnimalRemoved(object sender, AnimalListEventArgs e);

    /// <summary>
    /// MyAnimalList class only accept Animal types
    /// </summary>
    public class MyAnimalList : ArrayList
    {
        // An event that clients can use to be notified whenever the
        // elements of the list change.
        public event MyAnimals_AnimalRemoved AnimalRemoved;

        // Invoke the Changed event; called whenever list changes
        protected virtual void OnChanged(object sender, AnimalListEventArgs e) 
         {
             if (AnimalRemoved != null)
                 AnimalRemoved(this, e);
         }

         // Override some of the methods that can change the list;
         // invoke event after each
         public void Remove(int value)
         {
             MyAnimalList list = this;
             if (value > list.Count)
             {
                 MessageBox.Show(value+" is not a valid index", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                 return;
             }
             AnimalListEventArgs args = new AnimalListEventArgs((Animal)list[value]);
             OnChanged(this, args);
             base.Remove(value);
         }

         // Override some of the methods that can change the list;
         // invoke event after each
         public override void RemoveRange(int from,int to)
         {
             ArrayList list = this.GetRange(from, to);
             foreach(var animal in list)
             {
                 OnChanged(this, new AnimalListEventArgs((Animal)list[list.IndexOf(animal)]));
             }
             base.RemoveRange(from,to);
         }

         // Override some of the methods that can change the list;
         // invoke event after each
         public override void RemoveAt(int value)
         {
             MyAnimalList list = this;
             OnChanged(this, new AnimalListEventArgs((Animal)list[value]));
             base.RemoveAt(value);
         }

        /// <summary>
        /// Override + operator 
        /// </summary>
        /// <param name="list"></param>
        /// <param name="animal"></param>
        /// <returns></returns>
        public static MyAnimalList operator +(MyAnimalList list,Animal animal)
        {
            list.Add(animal);
            return list;
        }

        public new void Add(object value)
        {
            Type t = value.GetType();
            if (t.Equals(typeof(Animal)))
            {
                 base.Add((Animal)value);
            }
            else
            {
                MessageBox.Show("Only Animal type objects can be added to the MyAnimalList collection", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
           
        }
    }
}

And also i have extended EventArgs class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AnimalList
{
   public class AnimalListEventArgs:EventArgs
    {
       private readonly Animal animal;

       public AnimalListEventArgs(Animal animal)
       {
            this.animal = animal;
       }

       public Animal Animal
        {
            get { return this.animal; }
        }
    }
}

Here is my program class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AnimalList
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("||-- Starting animal program -- ||");

            MyAnimalList MyAnimals = new MyAnimalList();
            MyAnimals.AnimalRemoved += new MyAnimals_AnimalRemoved(ListChanged);

            MyAnimals.Add(new Animal(AnimalType.Amphibian, "Frog"));
            MyAnimals.Add(new Animal(AnimalType.Bird, "Eagle"));
            MyAnimals.Add(new Animal(AnimalType.Fish, "Bass"));

            MyAnimals += new Animal(AnimalType.Invertebrate, "Worm");
            MyAnimals += new Animal(AnimalType.Mammal, "Lion");
            MyAnimals += new Animal(AnimalType.Reptile, "Snake");

            MyAnimals.Add("dog");

            MyAnimals.Remove(5);
            MyAnimals.RemoveAt(3);
            MyAnimals.RemoveRange(1, 2);
            MyAnimals.Remove(5);

            foreach (Animal animal in MyAnimals)
            {
                MessageBox.Show("You still have a " + animal.AnimalName + " (" + animal.AnimalType + ")", "CS559 - Assignment 2", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

        }

        // This will be called whenever the list changes.
        private static void ListChanged(object sender, AnimalListEventArgs e)
        {
            MessageBox.Show(e.Animal.AnimalName +" was removed from the list.", e.Animal.AnimalType+" Removed", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}

How to read excel file using c#

Today I am going to show you how read excel file using c# and create folders based on excel file. Sometimes we may want to create many folders/sub folders based on business requirement and copy files into respective directory. So I am going to show how to do this using c# .net language. For this project i am using

  • Microsoft Visual Studio 2013
  • .net framework 4.5
  • ExcelDataReader library ( You can find it here)
  • Sample excel file which contain sample data set

Here is my project structure.

structure
Project Structure

Sample output

sample_output_parent
Parent folders
sample_output_child
Child folders

I have created sample console application to perform this task. I haven’t add exception handling for this code and feel free to optimize code and use it.

using Excel;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FolderProject
{
    /// <summary>
    /// Author : Damith Wanninayake
    /// Excel 4.5 library url:https://github.com/ExcelDataReader/ExcelDataReader
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            FileStream stream = File.Open(ConfigurationManager.AppSettings["sourceFile"], FileMode.Open, FileAccess.Read);
            string basePath = ConfigurationManager.AppSettings["basePath"];

            // Reading from a OpenXml Excel file (2007 format; *.xlsx)
            IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);

            // DataSet - Create column names from first row
            excelReader.IsFirstRowAsColumnNames = true;
            DataSet result = excelReader.AsDataSet();

            // Getting distinct values
            var distinctValues = result.Tables[0].AsEnumerable()
                        .Select(row => new
                        {
                            Mem = row.Field<double>("Mem#"),

You can find the completed project which contains excel file in here. Please note that i am not the author of the excel file.