Message Context and MassTransit

Did you know that MassTransit has the ability to ‘smuggle’ data? Now maybe smuggle isn’t the right word, but messages in MassTransit have the ability to carry ‘more’ than one contract of data.

For example, at work, some of our integration partners provide us with extra data that we need later on in the order life cycle. This data is unique to the provider. In the past this lead to the usage of some patterns I dislike such as the ‘mystery meat’ where we stuff data into a dictionary and use magic strings later to get it
back out.

public interface RegisterSalesOrderWithMysterMeat
{
    string OrderId { get; }
    //other properties
    IDictionary<string, string> MysteryMeat { get; }
}

the alternative of course is to extend your nice clean model with partner specific payload

public interface RegisterSalesOrderWithMoreStuff
{
    string OrderId { get; }
    //other properties

    //shopify stuff
    string ShopifyOneOff { get; }

    //bigcommerce stuff
    string BigCommerceOneOff { get; }
}

I am not a fan of either of these approaches. A third approach creates a message per integration partner, not a bad approach either in my book, but today I want to show of the Message Context in MassTransit, so I am going to ignore it.

Check this out

public class RegisterSalesOrderConsumer :
    Consumes<RegisterSalesOrder>.Context
{
    public void Consume(IConsumeContext<RegisterSalesOrder> context)
    {
        //normal payload
        var salesOrder = context.Message;

        IConsumerContext<RegisterShopifySalesOrder> shopifyDataContext;
        if(context.TryGetContext<RegisterShopifySalesOrder>(out shopifyDataContext))
        {
            //do stuff w/ shopifyData
            var shopifyData = shopifyDataContext.Message;
        }
    }
}

How sweet is that?!

How do you do it?

First you define your contracts with an interface rather than a class.

public interface RegisterSalesOrder
{
    string OrderId { get; }
    //other properties
}

public interface RegisterShopifySalesOrder
{
    //shopify stuff
    string ShopifyOneOff { get; }
}

public interface RegisterBigCommerceSalesOrder
{
    //bigcommerce stuff
    string BigCommerceOneOff { get; }
}

Then at your edge you have a class implement the correct interface.

public class RegisterShopifySalesOrderCommand :
    RegisterSalesOrder, RegisterShopifySalesOrder
{
    //implement the properties
}

public class RegisterBigCommerceSalesOrderCommand :
    RegisterSalesOrder, RegisterBigCommerceSalesOrder
{
    //implement the properties
}

and then publish the concrete class

bus.Publish(new RegisterBigCommerceSalesOrderCommand());

MassTransit will take care of routing the message for you, and now you can add additional content that may or may not be required. This isn’t a feature I recommend abusing, but its one more sharp tool in your toolbox.

About Dru Sellers

Sr. Software Engineer at Dovetail Software.
This entry was posted in MassTransit. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • eautcoins.com

    Thanks for you message and I will have a try!!