Search code examples
c#.netmasstransitautomatonymous

Getting ConsumeContext not available when using MassTransit and Automatonymous Publish after previously using RaiseEvent


If we set up a Saga and immediately Publish(context => ...) then a message successfully hits the bus.

If however, we have something like

Initially(
  When(SomeCommand)
     .Then(context => { context.Instance.SomeField = 5 })
     .TransitionTo(SomeState)
     .Then(context => this.RaiseEvent(context.Instance, SomeEvent)));

During(SomeState,
  When(SomeEvent)
     // ConsumeContext is not available here
     .Publish(context => new SomeEventClass
        {
           Foo = context.Instance.SomeField
        })
     .Finalize());

The machine also never transitions to the Final state presumably because of the exception locating a ConsumeContext.

We have seen some references to passing a ConsumeContext as a parameter in Publish() however it's unclear as to which context this needs (Intellisense just makes reference to context1, context2, context3, etc).

Is there a way to use Publish() after RaiseEvent() has already been called? If not, is there a way to publish an event using some other mechanism?

MassTransit version is 5.1.5 and Automatonymous is 4.1.2


EDIT Based on Chris Patterson's answer here we have tried adding the below outside of any Initially or During

WhenEnter(NewState, state => state.Publish(context => 
    new EventClass { Foo = context.Instance.Foo }
  )
  .Finalize();

However it still doesn't publish anything and the state never transitions to Final. If we add a Then it also never hits this code block. There don't seem to be any exceptions occurring. We also tried using When(SomeState.Enter) and it also doesn't work.

Side question as maybe this will help with my understanding of why Publish and RaiseEvent don't seem to play nicely together - why does Publish need the ConsumeContext? Is it to locate the bus and bindings?


Solution

  • The solution to this turned out to be using this:

    .Then(context => context.Raise(SomeEvent))
    

    instead of this:

    .Then(context => this.RaiseEvent(context.Instance, SomeEvent))
    

    It kinda makes sense now - the latter (as mentioned by Chris Patterson) creates a new EventContext while the former uses the given context. We didn't know that Raise was a method available on the passed in context.