# 7.0.4
Version 7.0.4 includes several new features which are detailed below. There were also numerous bug fixes, as well as tweaks to job consumers and batch consumers.
# General
MassTransit now references the .NET Core 2.1 version of Microsoft.Extensions.Logging.Abstractions, which should now make v7 usable with that SDK version.
The endpoint name formatters now support adding a prefix to all endpoint names, including the namespace in addition to the type name, and creating instance-specific queues for consumers.
services.AddMassTransit(x =>
{
x.AddConsumer<CommonConsumer>()
.Endpoint(e => e.InstanceId = "SomeUniqueValue");
});
This would format the endpoint name as either CommonSomeUniqueValue
, common_some_unique_value
, or common-some-unique-value
.
The prefix can be specified on the endpoint name formatter, as well as whether or not to include the namespace in the endpoint name.
services.AddSingleton<IEndpointNameFormatter>(provider => new KebabCaseEndpointNameFormatter("Dev", true));
This would format the endpoint name as dev-my-service-contacts-common
, assuming that CommonConsumer
was in the MyService.Contracts
namespace.
# Transports
# Amazon SNS
Topics are no longer created for published message types that include/implement other message types. Since SNS does not support polymorphic message routing, these topics were extraneous.
Queue attributes are now copied to error/skipped queues.
# RabbitMQ, Azure Service Bus
Message types can now be excluded from being created as exchanges or topics. Some other frameworks have stereotype interfaces such as IAmAnEvent
or IAmACommand
, or even base type interfaces like IShouldBeTreatedAsAMessage
, and those interfaces would be used to create exchanges/topics for polymorphic message support. These interfaces can now be excluded using the publish topology configuration.
Using an attribute, a type can be excluded:
[ExcludeFromTopology]
public interface IEvent
{
Guid TransactionId { get; }
}
The alternative is to configure the publish topology message type:
Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.Publish<IEvent>(p => p.Exclude = true);
});
# Containers
# In-Memory Test Harness
Registration for the test harness has been added, making it easier to test consumers using a container. To configure the in-memory test harness, see the example below.
var provider = new ServiceCollection()
.AddMassTransitInMemoryTestHarness(cfg =>
{
cfg.AddConsumer<PingRequestConsumer>();
})
.BuildServiceProvider(true);
var harness = provider.GetRequiredService<InMemoryTestHarness>();
await harness.Start();
try
{
var bus = provider.GetRequiredService<IBus>();
IRequestClient<PingMessage> client = bus.CreateRequestClient<PingMessage>();
await client.GetResponse<PongMessage>(new PingMessage());
Assert.That(await harness.Consumed.Any<PingMessage>());
}
finally
{
await harness.Stop();
await provider.DisposeAsync();
}
To include a consumer test harness for a consumer, additional configuration is required.
var provider = new ServiceCollection()
.AddMassTransitInMemoryTestHarness(cfg =>
{
cfg.AddConsumer<PingRequestConsumer>();
cfg.AddConsumerTestHarness<PingRequestConsumer>();
})
.BuildServiceProvider(true);
var harness = provider.GetRequiredService<InMemoryTestHarness>();
await harness.Start();
try
{
var bus = provider.GetRequiredService<IBus>();
IRequestClient<PingMessage> client = bus.CreateRequestClient<PingMessage>();
await client.GetResponse<PongMessage>(new PingMessage());
Assert.That(await harness.Consumed.Any<PingMessage>());
var consumerHarness = provider.GetRequiredService<IConsumerTestHarness<PingRequestConsumer>>();
Assert.That(await consumerHarness.Consumed.Any<PingMessage>());
}
finally
{
await harness.Stop();
await provider.DisposeAsync();
}
Saga test harnesses can also be used, as shown below.
var provider = new ServiceCollection()
.AddMassTransitInMemoryTestHarness(cfg =>
{
cfg.AddSaga<TestSaga>()
.InMemoryRepository();
cfg.AddSagaTestHarness<TestSaga>();
})
.BuildServiceProvider(true);
var harness = provider.GetRequiredService<InMemoryTestHarness>();
await harness.Start();
try
{
_sagaId = Guid.NewGuid();
_testValueA = "TestValueA";
await harness.Bus.Publish(new A
{
CorrelationId = _sagaId,
Value = _testValueA
});
Assert.That(await harness.Published.Any<A>());
Assert.That(await harness.Consumed.Any<A>());
var sagaHarness = provider.GetRequiredService<ISagaTestHarness<TestSaga>>();
Assert.That(await sagaHarness.Consumed.Any<A>());
Assert.That(await sagaHarness.Created.Any(x => x.CorrelationId == _sagaId));
var saga = sagaHarness.Created.Contains(_sagaId);
Assert.That(saga, Is.Not.Null);
Assert.That(saga.ValueA, Is.EqualTo(_testValueA));
Assert.That(await harness.Published.Any<Aa>());
Assert.That(await harness.Published.Any<B>(), Is.False);
}
finally
{
await harness.Stop();
await provider.DisposeAsync();
}
# Scoped Filters
Container registration for Scoped filters is now optional.
# State Machine Activities
Container registration for state machine activities is now optional for Microsoft Extensions Dependency Injection and Autofac.
← 7.0.6 Configuration →