.NET MSMQ - 1.0

Extension ID

com.castsoftware.dotnet.msmq

What’s new?

See .NET MSMQ - 1.0 - Release Notes.

Description

This extension provides support for MSMQ .NET APIs which are responsible for send and receive operations in .NET applications. If your C# application utilizes MSMQ for messaging-related operations, the send and receive are handled using the C# language, and you want to modelize the sender and receiver links with appropriate objects and links, then you should install this extension.

Supported libraries

Library Version Supported
System.Messagingexternal link up to: 4.x
MSMQ.Messagingexternal link up to 1.x

Compatibility

Core release Operating System Supported
8.4.x Microsoft Windows / Linux
8.3.x Microsoft Windows

Dependencies with other extensions

Some CAST extensions require the presence of other CAST extensions in order to function correctly. The .NET NMS extension requires that the following other CAST extensions are also installed (this will be managed automatically):

Download and installation instructions

The extension will not be automatically downloaded and installed. If you need to use it, you should manually install the extension.

What results can you expect?

Objects

Icon Description
MSMQ Sender
MSMQ Receiver
MSMQ unknown Sender
MSMQ unknown Receiver
Link Type Source and Destination of link Supported APIs
callLink callLink between the caller C# method and the Sender object System.Messaging.MessageQueue.Send
MSMQ.Messaging.MessageQueue.Send
callLink callLink between the Receiver object and the caller C# method System.Messaging.MessageQueue.Receive
System.Messaging.MessageQueue.ReceiveById
System.Messaging.MessageQueue.ReceiveByCorrelationId
System.Messaging.MessageQueue.BeginReceive
System.Messaging.MessageQueue.ReceiveByLookupId
System.Messaging.MessageQueue.Peek
System.Messaging.MessageQueue.PeekById
System.Messaging.MessageQueue.PeekByCorrelationId
System.Messaging.MessageQueue.PeekByLookupId
System.Messaging.MessageQueue.BeginPeek
System.Messaging.MessageQueue.GetAllMessages
MSMQ.Messaging.MessageQueue.Receive
MSMQ.Messaging.MessageQueue.ReceiveById
MSMQ.Messaging.MessageQueue.ReceiveByLookupId
MSMQ.Messaging.MessageQueue.ReceiveByCorrelationId
MSMQ.Messaging.MessageQueue.Peek
MSMQ.Messaging.MessageQueue.PeekById
MSMQ.Messaging.MessageQueue.PeekByCorrelationId
MSMQ.Messaging.MessageQueue.PeekByCorrelationId
MSMQ.Messaging.MessageQueue.PeekByLookupId
MSMQ.Messaging.MessageQueue.BeginPeek
MSMQ.Messaging.MessageQueue.BeginReceive
MSMQ.Messaging.MessageQueue.GetAllMessages

Example code scenarios

System.Messaging

Sender APIs

using System;
using System.Collections.Generic;
using System.Messaging;
using Castle.Windsor;
using DddCqrsEsExample.Framework;
using Newtonsoft.Json;

namespace DddCqrsEsExample.Web2.Infrastructure
{
    public class MsmqEventBus : IEventBus
    {
        private readonly IWindsorContainer _container;

        private const string QueueName = @".\private$\DddCqrsEsQueue";

        public MsmqEventBus(IWindsorContainer container)
        {
            if (container == null) throw new ArgumentNullException(nameof(container));
            _container = container;
        }

        public void Publish<TEvent>(TEvent evt) where TEvent : Event
        {
            HandleEvent(evt);

            PublishOnMsmq(evt);
        }

        private void HandleEvent<TEvent>(TEvent evt) where TEvent : Event
        {
            var handlerType = typeof(IEventHandler<>).MakeGenericType(evt.GetType());
            var handlers = _container.ResolveAll(handlerType);
            foreach (var handler in handlers)
            {
                try
                {
                    var handleMethod = handler.GetType().GetMethod("Handle");
                    handleMethod.Invoke(handler, new object[] {evt});
                }
                finally
                {
                    _container.Release(handler);
                }
            }
        }

        private static void PublishOnMsmq<TEvent>(TEvent evt) where TEvent : Event
        {
            if (!MessageQueue.Exists(QueueName))
            {
                MessageQueue.Create(QueueName);
            }

            using (var q = new MessageQueue(QueueName))
            {
                q.DefaultPropertiesToSend.Recoverable = true;

                q.Send(JsonConvert.SerializeObject(evt, Formatting.Indented) + "|" + evt.GetType().AssemblyQualifiedName);
            }
        }

Receiver APIs

using System;
using System.Messaging;
using DddCqrsEsExample.Framework;
using DddCqrsEsExample.ThinReadLayer.Core;
using Newtonsoft.Json;

namespace DddCqrsEsExample.ThinReadLayer.EventListener
{
    public class Listener
    {
        private const string QueueName = @".\private$\DddCqrsEsQueue";
        private MessageQueue _listeningQueue;

        public void Start()
        {
            if (!MessageQueue.Exists(QueueName))
            {
                MessageQueue.Create(QueueName);
            }

            try
            {
                if (MessageQueue.Exists(QueueName))
                {
                    _listeningQueue = new MessageQueue(QueueName);
                    _listeningQueue.ReceiveCompleted +=
                        (sender, args) =>
                        {
                            args.Message.Formatter = new XmlMessageFormatter(new[] {typeof(string)});
                            var msg = args.Message.Body.ToString();

                            Console.WriteLine("Message received:{0}", msg);

                            var parts = msg.Split('|');
                            var json = parts[0];
                            var typeName = parts[1];
                            var type = Type.GetType(typeName);
                            var evt = (Event)JsonConvert.DeserializeObject(json, type);

                            new Denormaliser().StoreEvent(evt);

                            _listeningQueue.BeginReceive();
                        };
                    _listeningQueue.BeginReceive();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(string.Format("Unable to initialise message queue on your local machine.\r\n\r\n{0}", e));
            }
        }
    }
}

Dotnet Sender and Receiver

When the queue path matches for both the sender and receiver, a callLink will be established between the sender object and the receiver object:

Known limitations

  • Unknown Sender/Receiver objects will be created if the evaluation fails to resolve the necessary parameter.