Publish messages with the AWS Message Processing Framework for .NET
Note
This is prerelease documentation for a feature in preview release. It is subject to change.
The AWS Message Processing Framework for .NET supports publishing one or more message types, processing one or more message types, or doing both in the same application.
The following code shows a configuration for an application that is publishing different message types to different AWS services.
var builder = WebApplication.CreateBuilder(args);
// Register the AWS Message Processing Framework for .NET
builder.Services.AddAWSMessageBus(builder =>
{
// Register that you'll send messages of type ChatMessage to an existing queue
builder.AddSQSPublisher<ChatMessage>("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd");
// Register that you'll publish messages of type OrderInfo to an existing SNS topic
builder.AddSNSPublisher<OrderInfo>("arn:aws:sns:us-west-2:012345678910:MyAppProd");
// Register that you'll publish messages of type FoodItem to an existing EventBridge bus
builder.AddEventBridgePublisher<FoodItem>("arn:aws:events:us-west-2:012345678910:event-bus/default");
});
Once you have registered the framework during startup, inject the generic
IMessagePublisher
into your code. Call its PublishAsync
method to publish any
of the message types that were configured above. The generic publisher will determine the destination to
route the message to based on its type.
In the following example, an ASP.NET MVC controller receives both ChatMessage
messages
and OrderInfo
events from users, and then publishes them to Amazon SQS and Amazon SNS respectively.
Both message types can be published using the generic publisher that was configured above.
[ApiController]
[Route("[controller]")]
public class PublisherController : ControllerBase
{
private readonly IMessagePublisher _messagePublisher;
public PublisherController(IMessagePublisher messagePublisher)
{
_messagePublisher = messagePublisher;
}
[HttpPost("chatmessage", Name = "Chat Message")]
public async Task<IActionResult> PublishChatMessage([FromBody] ChatMessage message)
{
// Perform business and validation logic on the ChatMessage here.
if (message == null)
{
return BadRequest("A chat message was not submitted. Unable to forward to the message queue.");
}
if (string.IsNullOrEmpty(message.MessageDescription))
{
return BadRequest("The MessageDescription cannot be null or empty.");
}
// Send the ChatMessage to SQS, using the generic publisher.
await _messagePublisher.PublishAsync(message);
return Ok();
}
[HttpPost("order", Name = "Order")]
public async Task<IActionResult> PublishOrder([FromBody] OrderInfo message)
{
if (message == null)
{
return BadRequest("An order was not submitted.");
}
// Publish the OrderInfo to SNS, using the generic publisher.
await _messagePublisher.PublishAsync(message);
return Ok();
}
}
In order to route a message to the appropriate handling logic, the framework uses metadata called the message type identifier. By default, this is the full name of the message's .NET type, including its assembly name. If you're both sending and handling messages, this mechanism works well if you share the definition of your message objects across projects. However, if the messages are redefined in different namespaces, or if you're exchanging messages with other frameworks or programming languages, then you might need to override the message type identifier.
var builder = Host.CreateDefaultBuilder(args);
builder.ConfigureServices(services =>
{
// Register the AWS Message Processing Framework for .NET
services.AddAWSMessageBus(builder =>
{
// Register that you'll publish messages of type GreetingMessage to an existing queue
builder.AddSQSPublisher<GreetingMessage>("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd", "greetingMessage");
});
});
Service-specific publishers
The example shown above uses the generic IMessagePublisher
, which can publish to any
supported AWS service based on the configured message type. The framework also provides
service-specific publishers for Amazon SQS, Amazon SNS and Amazon EventBridge. These specific publishers expose options that
only apply to that service, and can be injected using the types ISQSPublisher
,
ISNSPublisher
, and IEventBridgePublisher
.
For example, when sending messages to an SQS FIFO queue, you must set the appropriate message group
ID. The following code shows the ChatMessage
example again, but now using an
ISQSPublisher
to set SQS-specific options.
public class PublisherController : ControllerBase
{
private readonly ISQSPublisher _sqsPublisher;
public PublisherController(ISQSPublisher sqsPublisher)
{
_sqsPublisher = sqsPublisher;
}
[HttpPost("chatmessage", Name = "Chat Message")]
public async Task<IActionResult> PublishChatMessage([FromBody] ChatMessage message)
{
// Perform business and validation logic on the ChatMessage here
if (message == null)
{
return BadRequest("A chat message was not submitted. Unable to forward to the message queue.");
}
if (string.IsNullOrEmpty(message.MessageDescription))
{
return BadRequest("The MessageDescription cannot be null or empty.");
}
// Send the ChatMessage to SQS using the injected ISQSPublisher, with SQS-specific options
await _sqsPublisher.SendAsync(message, new SQSOptions
{
DelaySeconds = <delay-in-seconds>,
MessageAttributes = <message-attributes>,
MessageDeduplicationId = <message-deduplication-id>,
MessageGroupId = <message-group-id>
});
return Ok();
}
}
The same can be done for SNS and EventBridge, using ISNSPublisher
and
IEventBridgePublisher
respectively.
await _snsPublisher.PublishAsync(message, new SNSOptions
{
Subject = <subject>,
MessageAttributes = <message-attributes>,
MessageDeduplicationId = <message-deduplication-id>,
MessageGroupId = <message-group-id>
});
await _eventBridgePublisher.PublishAsync(message, new EventBridgeOptions
{
DetailType = <detail-type>,
Resources = <resources>,
Source = <source>,
Time = <time>,
TraceHeader = <trace-header>
});
By default, messages of a given type are sent to the destination that is configured in advance. However, you can override the destination for a single message using the message-specific publishers. You can also override the underlying AWS SDK for .NET client that is used to publish the message, which can be useful in multi-tenant applications where you need to change roles or credentials, depending on the destination.
await _sqsPublisher.SendAsync(message, new SQSOptions
{
OverrideClient = <override IAmazonSQS client>,
QueueUrl = <override queue URL>
});