Neil
Neil

Reputation: 11929

MassTransit - non-scoped publish fiters

I have created a Masstransit publish filter, that creates a message header, based on information provided by an accessor.

I want to set some values in the accessor, during processing, which will be picked up by the publish filter.

The way I understand filters, is that they are scoped, and therefore, any message published, will create a new DI scope. This means that the values I set before publishing the message, will not be available in the filter.

public interface IAccessor
{
   Guid Id {get;set;}
}

public class Accessor : IAccessor
{
   public Guid Id {get;set;}
}

public class MyPublishFilter<T> : IFilter<PublishContext<T>> where T : class 
{
    private readonly IAccessor accessor;
    public MyPublishFilter(IAccessor accessor) 
     => this.accessor = accessor; <-- this accessor is different to the one in MyProgram
    public async Task Send(PublishContext<T> context, IPipe<PublishContext<T>> next) 
    { 
        context.CorrelationId = accessor.Id; 
        await next.Send(context);
    }

public class MyProgram
{
    public MyProgram(IAccessor accessor) => this.accessor = accessor;
    public async Task DoThing()
    {
        accessor.Id = Guid.NewGuid();  <--- this value is not passed to the filter
        messageBus.Publish(new Message());
    }

}

Is there a way to tell MassTransit NOT to create a new scope for message filters?

Upvotes: 1

Views: 513

Answers (1)

Chris Patterson
Chris Patterson

Reputation: 33565

To use an existing scope, use IPublishEndpoint instead of IBus to publish the message. You should resolve IPublishEndpoint from the container scope service provider, and the scoped filter should use the same scope.

await using var scope = provider.CreateScope();

// use the scope to set your accessor Id

var publishEndpoint = scope.ServiceProvider.GetRequiredService<IPublishEndpoint>();

await publishEndpoint.Publish(...);

Upvotes: 1

Related Questions