8

I am using MassTransit 3.0.0.0 and I have a hard time understanding how to intercept messages in a Request-Response scenario on their way out and add some information to the headers field that I can read on the receiver's end.

I was looking at the Middleware, as recommended in the MassTransit docs - see Observers warning - but the context you get on the Send is just a Pipe context that doesn't have access to the Headers field so I cannot alter it. I used the sample provided in Middleware page.

I then, looked at IPublishInterceptor

public class X<T> : IPublishInterceptor<T> where T : class, PipeContext
{
    public Task PostPublish(PublishContext<T> context)
    {
        return new Task(() => { });
    }

    public Task PostSend(PublishContext<T> context, SendContext<T> sendContext)
    {
        return new Task(() => { });
    }

    public Task PrePublish(PublishContext<T> context)
    {
        context.Headers.Set("ID", Guid.NewGuid().ToString());
        return new Task(() => { });
    }

    public Task PreSend(PublishContext<T> context, SendContext<T> sendContext)
    {
        context.Headers.Set("ID", Guid.NewGuid().ToString());
        return new Task(() => { });
    }
}

Which is very clear and concise. However, I don't know where it is used and how to link it to the rest of the infrastructure. As it stands, this is just an interface that is not really linked to anything.

Wiebe Tijsma
  • 10,173
  • 5
  • 52
  • 68
Gradinariu Cezar
  • 553
  • 1
  • 5
  • 12

3 Answers3

8

If you need to add headers when a message is being sent, you can add middleware components to either the Send or the Publish pipeline as shown below. Note that Send filters will apply to all messages, whereas Publish filters will only apply to messages which are published.

// execute a synchronous delegate on send
cfg.ConfigureSend(x => x.Execute(context => {}));

// execute a synchronous delegate on publish
cfg.ConfigurePublish(x => x.Execute(context => {}));

The middleware can be configured on either the bus or individual receive endpoints, and those configurations are local to where it's configured.

Chris Patterson
  • 28,659
  • 3
  • 47
  • 59
7

You can also add headers in the consumer class:

public async Task Consume(ConsumeContext<MyMessage> context)
{
    ....
    await context.Publish<MyEvent>(new { Data = data }, c => AddHeaders(c));
}

public static void AddHeaders(PublishContext context)
{
    context.Headers.Set("CausationId", context.MessageId);
}
Alexey Zimarev
  • 17,944
  • 2
  • 55
  • 83
1

http://masstransit-project.com/MassTransit/advanced/middleware/custom.html

Shows adding an extension method to make it clear what you're setup. That's a big help if it's an interceptor that will be used a lot, so it's clear that purpose. You can skip that step if you want.

Basically, just...

cfg.AddPipeSpecification(new X<MyMessage>());

When configuring the transport.

Mr. Pumpkin
  • 6,212
  • 6
  • 44
  • 60
Travis
  • 10,444
  • 2
  • 28
  • 48
  • I know what you mean by sample using the extension methods. I tried the sample you sent, it doesn't work with the X type because that is a IPublishInterceptor and it expects an IPipeSpecification and there is no relationshipe between the 2. And PipeSpecification doesn't provide access to modify the Headers on the message. – Gradinariu Cezar Jan 28 '16 at 00:43
  • 1
    `cfg.AddPipeSpecification` only allows adding filters for the consume pipeline, as far I can read the signatures. – Alexey Zimarev Dec 30 '16 at 10:12