Reputation: 11929
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
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