.NET and Amazon Simple Notification Service (SNS)
Tags: aws, dotnet, eventdriven, architecture
Published: 2022-09-02 14:17:26

SNS, as you can probably guess from its name, is a straightforward service that uses pub\sub messaging to deliver messages. Pub\Sub, or Publish\Subscribe, messaging is an asynchronous communication method. This model includes the publisher who sends the data, a subscriber that receives the data, and the message broker that handles the coordination between the publisher and subscriber. In this case, [Amazon SNS](https://aws.amazon.com/sns) is the message broker because it handles the message transference from publisher to subscriber.

_**Note** – The language used when looking at events and messaging as we did in the [previous post](https://dev.to/aws-builders/modern-net-application-design-5gp9) can be confusing. Messaging is the pattern we discussed last post. Messages are the data being sent and are part of both events and messaging. The term “message” is considered interchangeable with notification or event – even to the point where you will see articles about the messaging pattern that refer to the messages as events._

The main responsibility of the message broker is to determine which subscribers should be sent what messages. It does this using a topic. A topic can be thought of as a category that describes the data contained within the message. These topics are defined based on your business. There will be times that a broad approach is best, so perhaps topics for “Order” and “Inventory” where all messages for each topic are sent. Thus, the order topic could include messages for “Order Placed” and “Order Shipped” and the subscribers will get all of those messages. There may be other times where a very narrow focus is more appropriate, in which case you may have an “Order Placed” topic and an “Order Shipped” topic where systems can subscribe to them independently. Both approaches have their strength and weaknesses.

When you look at the concept of messaging, where one message has one recipient, the advantage that a service like SNS offers is the ability to distribute a single message to multiple recipients as shown in Figure 1, which is one of the key requisites of event-based architecture.

![Figure 1. Pub\Sub pattern using Amazon SNS](https://i0.wp.com/billthevestguy.com/wp-content/uploads/2022/09/image.png)_Figure 1. Pub\Sub pattern using Amazon SNS_

Now that we have established that SNS can be effectively used when building in an event-based architecture, let’s go do just that!

## Using AWS Toolkit for Visual Studio

If you’re a Visual Studio user, you can do a lot of the configuration and management through the toolkit. Going into Visual Studio and examining the AWS Explorer will show that one of the options is Amazon SNS. At this point, you will not be able to expand the service in the tree control because you have not yet started to configure it. Right-clicking on the service will bring up a menu with three options, _Create topic_, _View subscriptions_, and _Refresh_. Let’s get started by creating our first topic. Click on the **Create topic** link and create a topic. We created a topic named “ProDotNetOnAWS” – it seems to be a trend... Once you save the topic you will see it show up in the AWS Explorer.

Right-click on the newly created topic and select to **View topic**. This will add the topic details screen into the main window as shown in Figure 2.

![Figure 2. SNS topic details screen in the Toolkit for Visual Studio](https://i0.wp.com/billthevestguy.com/wp-content/uploads/2022/09/image-1.png)_Figure 2. SNS topic details screen in the Toolkit for Visual Studio_

In the details screen, you will see a button to **Create New Subscription**. Click this button to bring up the _Create New Subscription_ popup window. There are two fields that you can complete, _Protocol_ and _Endpoint_. The protocol field is a dropdown and contains various choices.

### HTTP or HTTPS Protocol Subscription

The first two of these choices are **HTTP** and **HTTPS**. Choosing one of these protocols will result in SNS making an HTTP (or HTTPS) POST to the configured endpoint. This POST will result in a JSON document with the following name-value pairs.

- **Message** – the content of the message that was published to the topic
- **MessageId** – A universally unique identifier for each message that was published
- **Signature** – Base64-encoded signature of the Message, MessageId, Subject, Type, Timestamp, and TopicArn values.
- **SignatureVersion** – version of the signature used
- **SigningCertUrl** – the URL of the certificate that was used to sign the message
- **Subject** – the optional subject parameter used when the notification was published to a topic. In those examples where the topic is broadly-based, the subject can be used to narrow down the subscriber audience.
- **Timestamp** – the time (GMT) when the notification was published.
- **TopicARN** – the Amazon Resource Name (ARN) for the topic
- **Type** – the type of message being sent. For an SNS message, this type is _Notification_.

At a minimum, your subscribing system will care about the message, as this message contains the information that was provided by the publisher. One of the biggest advantages of using an HTTP or HTTPS protocol subscription is that the system that is subscribed does not have to do anything other than accept the message that is submitted. There is no special library to consume, no special interactions that must happen, just an endpoint that accepts requests.

Some considerations as you think about using SNS to manage your event notifications. There are several different ways to manage the receipt of these notifications. The first is to create a single endpoint for each topic to which you subscribe. This makes each endpoint very discrete and only responsible for handling one thing; usually considered a plus in the programming world. However, this means that the subscribing service has some limitations as there are now external dependencies on multiple endpoints. Changing an endpoint URL, for example, will now require coordination across multiple systems.

On the other hand, there is another approach where you create a single endpoint that acts as the recipient of messages across multiple topics. The code within the endpoint identifies the message and then forwards it through the appropriate process. This approach abstracts away any work within the system, as all of those changes happen below this single broadly bound endpoint. We have seen both of those approaches working successfully, it really comes down to your own business needs and how you see your systems evolving as you move forward.

### Other Protocol Subscriptions

There are other protocol subscriptions that are available in the toolkit. The next two in the list are _Email and Email (JSON)_. Notifications sent under this protocol are sent to the email address that is entered as the endpoint value. This email is sent in two ways, where the Message field of the notification becomes the body of the email or where the email body is a JSON object very similar to that used when working with the HTTP\HTTPS protocols. There are some business-to-business needs for this, such as sending a confirmation to a third party upon processing an order; but you will generally find any discussion of these two protocols under Application-to-Person (A2P) in the documentation and examples.

The next protocol that is available in the toolkit is _Amazon SQS_. Amazon Simple Queue Service (SQS) is a queue service that follows the messaging pattern that we discussed earlier where one message has one recipient and one recipient only.

The last protocol available in the toolkit is _Lambda_. Choosing this protocol means that a specified Lambda function will be called with the message payload being set as an input parameter. This option makes a great deal of sense if you are building a system based on serverless functions. Of course, you can also use HTTP\HTTPS protocol and make the call to the endpoint that surfaces the Lambda method; but using this direct approach will remove much of that intermediate processing.

Choosing either the SQS or Lambda protocols will activate the _Add permission for SNS topic to send messages to AWS resources_ checkbox as shown in Figure 3.

![Figure 3. Create New Subscription window in the Toolkit for Visual Studio](https://i0.wp.com/billthevestguy.com/wp-content/uploads/2022/09/image-2.png)_Figure 3. Create New Subscription window in the Toolkit for Visual Studio_

Checking this box will create the necessary permissions allowing the topic to interact with AWS resources. This is not necessary if you are using HTTP\HTTPS or Email.

For the sake of this walk-through, we used an approach that is ridiculous for enterprise systems; we selected the Email (JSON) protocol. Why? So we could easily show you the next few steps in a way that you could easily duplicate. This is important because all you can do in the Toolkit is to create the topic and the subscription. However, as shown in Figure 4, this leaves the subscription in a _PendingConfirmation_ state.

![Figure 4. Newly created SNS topic subscription in Toolkit for Visual Studio](https://i0.wp.com/billthevestguy.com/wp-content/uploads/2022/09/image-3.png)_Figure 4. Newly created SNS topic subscription in Toolkit for Visual Studio_

Subscriptions in this state are not yet fully configured, as they need to be confirmed before they are able to start receiving messages. Confirmation happens after a _SubscriptionConfirmation_ message is sent to the endpoint, which happens automatically when creating a new subscription through the Toolkit. The JSON we received in email is shown below:

```
{
  "Type" : "SubscriptionConfirmation",
  "MessageId" : "b1206608-7661-48b1-b82d-b1a896797605",
  "Token" : "TOKENVALUE", 
  "TopicArn" : "arn:aws:sns:xxxxxxxxx:ProDotNetOnAWS",
  "Message" : "You have chosen to subscribe to the topic arn:aws:sns:xxxxxxx:ProDotNetOnAWS.\nTo confirm the subscription, visit the SubscribeURL included in this message.",
  "SubscribeURL" : "https://sns.us-west-2.amazonaws.com/?Action=ConfirmSubscription&TopicArn=xxxxxxxx",
  "Timestamp" : "2022-08-20T19:18:27.576Z",
  "SignatureVersion" : "1",
  "Signature" : "xxxxxxxxxxxxx==",
  "SigningCertURL" : "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-56e67fcb41f6fec09b0196692625d385.pem"
}
```
The _Message_ indicates the action that needs to be taken – you need to visit the **SubscribeURL** that is included in the message. Clicking that link will bring you to a confirmation page in your browser like that shown in Figure 5.

![Figure 5. Subscription confirmation message displayed in browser](https://i0.wp.com/billthevestguy.com/wp-content/uploads/2022/09/image-4.png)_Figure 5. Subscription confirmation message displayed in browser_

Refreshing the topic in the Toolkit will show you that the _PendingConfirmation_ message is gone and has been replaced with a real _Subscription ID_.

## Using the Console

The process for using the console is very similar to the process we just walked through in the Toolkit. You can get to the service by searching in the console for Amazon SNS or by going into the _Application Integration_ group under the services menu. Once there, select **Create topic**. At this point, you will start to see some differences in the experiences.

The first is that you have a choice on the topic _Type_, as shown in Figure 6. You can select from _FIFO (first-in, first-out)_ and _Standard_. FIFO is selected by default. However, selecting FIFO means that the service will follow the messaging architectural approach that we went over earlier where there is exactly-once message delivery and message ordering is strictly preserved. The Standard type, on the other hand, supports “at least once message delivery” which means that it supports multiple subscriptions.

![Figure 6. Creating an SNS topic in the AWS Console](https://i0.wp.com/billthevestguy.com/wp-content/uploads/2022/09/image-5.png)_Figure 6. Creating an SNS topic in the AWS Console_

Figure 6 also displays a checkbox labeled _Content-based message deduplication_. This selection is only available when _FIFO_ type is selected. When selected, the message being sent is assumed to be unique and SNS will not provide a unique deduplication value. Otherwise, SNS will add a unique value to each message that it will use to determine whether a particular message has been delivered.

Another difference between creating a topic in the console vs in the toolkit is that you can optionally set preferences around message encryption, access policy, delivery status logging, delivery retry policy (HTTP\S), and, of course, tags. Let’s look in more detail at two of those preferences. The first of these is the _Delivery retry policy_. This allows you to set retry rules for how SNS will retry sending failed deliveries to HTTP/S endpoints. These are the only endpoints that support retry. You can manage the following values:

- **Number of retries** – defaults to 3 but can be any value between 1 and 100
- **Retries without delay** – defaults to 0 and represents how many of those retries should happen before the system waits for a retry
- **Minimum delay** – defaults to 20 seconds with a range from 1 to the value of the Maximum delay.
- **Maximum delay** – defaults to 20 seconds with a range from the Minimum delay to 3,600.
- **Retry backoff function** – defaults to linear. There are four options, _Exponential_, _Arithmetic_, _Linear_, and _Geometric_. Each of those functions processes the timing for retries differently. You can see the differences between these options at [https://docs.aws.amazon.com/sns/latest/dg/sns-message-delivery-retries.html](https://docs.aws.amazon.com/sns/latest/dg/sns-message-delivery-retries.html).

The second preference that is available in the console but not the toolkit is _Delivery status logging_. This preference will log delivery status to CloudWatch Logs. You have two values to determine. This first is _Log delivery status for these protocols_ which presents a series of checkboxes for _AWS Lambda_, _Amazon SQS_, _HTTP/S_, _Platform application endpoint_, and _Amazon Kinesis Data Firehouse_. These last two options are a preview of the next big difference between working through the toolkit or through the console.

## Additional Subscriptions in the Console

Once you have finished creating the topic, you can then create a subscription. There are several protocols available for use in the console that are not available in the toolkit. These include:

- **Amazon Kinesis Data Firehouse** – configure this subscription to go to Kinesis Data Firehouse. From there you can send notifications to Amazon S3, Amazon Redshift, Amazon OpenSearch Service, and third-party service providers such as Datadog, New Relic, MongoDB, and Splunk.
- **Platform-application endpoint** – this protocol sends the message to an application on a mobile device. Push notification messages sent to a mobile endpoint can appear in the mobile app as message alerts, badge updates, or even sound alerts. Go to [https://docs.aws.amazon.com/sns/latest/dg/sns-mobile-application-as-subscriber.html](https://docs.aws.amazon.com/sns/latest/dg/sns-mobile-application-as-subscriber.html) for more information on configuring your SNS topic to deliver to a mobile device.
- **SMS** – this protocol delivers text messages, or SMS messages, to SMS-enabled devices. Amazon SNS supports SMS messaging in several regions, and you can send messages to more than 200 countries and regions. An interesting aspect of SMS is that your account starts in a SMS sandbox or non-production environment with a set of limits. Once you are convinced that everything is correct you must create a case with AWS support to move your account out of the sandbox and actually start sending messages to non-limited numbers.

Now that we have configured our SNS topic and subscription, lets next look at sending a message.

## .NET and Amazon SNS

The first step to interacting with SNS from within your .NET application is to install the appropriate NuGet package, **AWSSDK.SimpleNotificationService**. This will also install **AWSSDK.Core**. Once you have the NuGet package, you can access the appropriate APIs by adding several using statements

```
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;
```

These namespaces provide access to the **AmazonSimpleNotificationServiceClient** class that manages the interaction with the SNS service as well as the models that are represented in the client methods. There are a lot of different types of interactions that you can support with this client. A list of the more commonly used methods is displayed below:

- **PublishAsync** – Send a message to a specific topic for processing by SNS
- **PublishBatchAsync** – Send multiple messages to a specific topic for processing by SNS.
- **Subscribe** – Subscribe a new endpoint to a topic
- **Unsubscribe** – Remove an endpoint’s subscription to a topic.

These four methods allow you to add and remove subscriptions as well as publish messages. There are dozens of other methods available from that client, including the ability to manage topics and confirm subscriptions.

The code below is a complete console application that sends a message to a specific topic.

```
static void Main(string[] args)
{
    string topicArn = "Arn for the topic to publish";
    string messageText = "Message from ProDotNetOnAWS_SNS";

    var client = new AmazonSimpleNotificationServiceClient();

    var request = new PublishRequest
    {
        TopicArn = topicArn,
        Message = messageText,
        Subject = Guid.NewGuid().ToString()
    };

    var response = client.PublishAsync(request).Result;

    Console.WriteLine(
       $"Published message ID: {response.MessageId}");

    Console.ReadLine();
}
```

As you can see, the topic needs to be described with the _Arn_ for the topic rather than simply the topic name. Publishing a message entails the instantiation of the client and then defining a **PublishRequest** object. This object contains all of the fields that we are intending to send to the recipient, which in our case is simply the subject and message. Running the application presents a console as shown in Figure 7.

![Figure 7. Console application that sent message through SNS](https://i0.wp.com/billthevestguy.com/wp-content/uploads/2022/09/image-6.png)_Figure 7. Console application that sent message through SNS_

The message that was processed can be seen in Figure 8. Note the MessageId values are the same as in Figure 7.

![Figure 8. Message sent through console application](https://i0.wp.com/billthevestguy.com/wp-content/uploads/2022/09/image-7.png)_Figure 8. Message sent through console application_ 

We have only touched on the capabilities of Amazon SNS and its capacity to help implement event-driven architecture. However, there is another AWS service that is even more powerful, Amazon EventBridge. Let’s look at that in the next post.