Message Routes
Configure a message route
Section titled “Configure a message route”Message routes are configured inside the AddMassTransit method.
services.AddMassTransit(x =>{ x.AddMessageRoute<UpdateCustomerAddress>((provider, message) => new Uri($"queue:customer_address_update&bind=false"));});Configure consumer message routes
Section titled “Configure consumer message routes”When adding a consumer, you can configure messages routes for all message types consumed by the consumer using the IncludeMessageRoutes method.
services.AddMassTransit(x =>{ x.AddConsumer<SubmitOrderConsumer>() .IncludeMessageRoutes();});Send using message routes
Section titled “Send using message routes”Once the message route is configured, you can use the IScopedBus to send a message.
public async Task SomeControllerMethod([FromBody] UpdateCustomerAddress model, [FromServices] IScopedBus bus){ var message = new UpdateCustomerAddress(model.CustomerId, model.Address);
await bus.Send(message);}If you are using MultiBus, you can use the IScopedBus<TBus> to send a message using a specific bus instance.
public async Task SomeControllerMethod([FromBody] UpdateCustomerAddress model, [FromServices] IScopedBus<ISecondBus> bus){ var message = new UpdateCustomerAddress(model.CustomerId, model.Address);
await bus.Send(message);}Using the old EndpointConvention
Section titled “Using the old EndpointConvention”Using send endpoints might seem too verbose, because before sending any message, you need to get the send endpoint and to do that you need to have an endpoint address. Usually, addresses are kept in the configuration, and accessing the configuration from all over the application is not a good practice.
Endpoint conventions solve this issue by allowing you to configure the mapping between message types and endpoint addresses. A potential downside here is that
you will not be able to send messages of the same type to different endpoints by using conventions. If you need to do this, keep using the GetSendEndpoint
method.
Conventions are configured like this:
EndpointConvention.Map<SubmitOrder>(new Uri("queue:order_processing&bind=false"));Now, you don’t need to get the send endpoint anymore for this type of message and can send it like this:
public async Task Post(SubmitOrderRequest request){ if (AllGoodWith(request)) await _bus.Send(ConvertToCommand(request));}Also, from inside the consumer, you can do the same using the ConsumeContext.Send overload:
EndpointConvention.Map<StartDelivery>( new Uri(ConfigurationManager.AppSettings["deliveryServiceQueue"]));public class SubmitOrderConsumer : IConsumer<SubmitOrder>{ private readonly IOrderSubmitter _orderSubmitter;
public SubmitOrderConsumer(IOrderSubmitter submitter) => _orderSubmitter = submitter;
public async Task Consume(IConsumeContext<SubmitOrder> context) { await _orderSubmitter.Process(context.Message);
await context.Send(new StartDelivery(context.Message.OrderId, DateTime.UtcNow)); }}The EndpointConvention.Map<T> method is static, so it can be called from everywhere. It is important to remember that you cannot configure conventions for the
same message twice. If you try to do this - the Map method will throw an exception. This is also important when writing tests, so you need to configure the
conventions at the same time as you configure your test bus (harness).
It is better to configure routes before you start the bus.