Use data from message handler in a behavior

Hello, I’m struggeling with the following:

I have a message handler that reads data from a database. If a record is found, some ID value is read.
If the message handler fails for whatever reason, but it fails after the ID has been read, I would like to add the ID to a message header so this ID will be part of the message in the error queue.

I know about the concept of NServiceBus Behaviors to manipulate headers, but I was not able to share data between a message handler and a behavior. Is this possible?

Thank you very much!

Hi @Jokelab ,

I’m not sure why you’d want to do that and if you could, I’d love to hear more details about the specific use case. Maybe there are other solutions that we can think of.

Here is a sample that shows an incoming behavior how to modify the message. That same can be done with outgoing messages.

The problem you’re having is that sharing data between behaviors and handlers isn’t as easy as you might want it to be.

In this sample about tenants you can see how you can inject sessions into messagehandlers that are tenant-specific.

Here’s more information about sharing data between behaviors.

But you can read here that sharing this information with a handler is better of done a slightly different way.

I hope that gets you on your way? Again, if you could let me know more context about the specific use case, I could potentially create a sample for this to share with you and possibly others.

Regards,
Dennis

Thank you for your swift response and the great examples!

Here are some more details about what we’re trying to do:

The message handler is triggered by an incoming message that was put directly on the queue by an external system. The message handler performs the following tasks as part of an ETL proces:

  • Get a resultset from a database
  • The resultset contains a ‘batch ID’ of the things to process.
  • For each item in the batch:
    – Send a message to another endpoint for further processing. The batch ID is copied to the item.

The external system cannot provide a unique key that we can use to identity the message.
If the message handler fails, we would like to “stamp” the message with the ID of the batch for two reasons:

  • If the message ends up in the error queue, the message would contain the batch ID which helps us to identify the root cause.
  • If the message is retried, we can use the batch ID to make sure we get the same dataset every time the message is processed.

I’ll have a look at the examples to see if they get me any further. If there are better ways to address this problem then I’m of course open to suggestions.

Thanks a bunch!
Robert

The unit of work example shows how to share data between the message handler and the incoming message stage. Unfortunately the ContextBag in the recoverability pipeline is not the same instance as the one in the incoming message pipeline. It’s therefore not possible to do the following:

     internal class RecoveryBehavior : Behavior<IRecoverabilityContext>
   {
       public override Task Invoke(IRecoverabilityContext context, Func<Task> next)
       {
           var batch = context.Extensions.Get<SharedData>(); //doesn't work
           context.Metadata["BatchId"] = batch.Id;
           return next();
       }
   }

Is there perhaps another way to achieve this? I also saw this example, but instead of using a static value I would like to use a value that’s only known after/during execution of the message handler.

Regards, Robert