.NET on AWS Blog

Event-driven .NET applications with AWS Lambda and Amazon EventBridge

Amazon EventBridge is a serverless event bus that lets you pass events between AWS services, your applications, and third party services, helping you to build event-driven applications. It implements the publisher/subscriber (pub/sub) pattern, where publishers emit events, and subscribers receive them.

As of this writing, over 150 AWS services generate EventBridge events. For example, you can use EventBridge to invoke a Lambda function when a file is uploaded to an Amazon S3 bucket, when an Amazon Translate job is complete, when an Amazon RDS instance is created, or when any of a hundred other events occur. The EventBridge service also has a scheduler service. It allows you to define the event to send, schedule its delivery, and define its targets.

This post will first give you a little background on EventBridge, and then show you how to use it to invoke a .NET Lambda function when a file is uploaded to an S3 bucket. You will need an AWS account and a working knowledge of AWS Lambda, Amazon S3, and Amazon CloudWatch Logs.

The Mechanics of EventBridge

To get started, you need to understand a few concepts:

  • Events
  • Event Buses
  • Event Rules

Events

An event is a JSON object that contains information about what happened, when it occurred, in what service, who did it, and in what region.

Events follow a standard format with two main sections: the header and the detail section.

The following is an example of an event header generated by Amazon S3 when a file is uploaded to a bucket:

{
    "version": "0",
    "id": "6a0dd55e-8c7e-9836-e064-859b90c7ad7f",
    "detail-type": "Object Created",
    "source": "aws.s3",
    "account": "694977046108",
    "time": "2023-03-23T15:33:44Z",
    "region": "us-east-1",
    "resources": [
        "arn:aws:s3:::test-bucket"
    ],
    "detail": { ...

The detail section contains information specific to the service that generated the event, and the event that occurred.

For example, in the case of a file uploaded to S3, the detail section of the event contains the bucket name, information about the S3 object that was created, and the IP address of the client that uploaded the file:

...],
"detail": {
        "version": "0",
        "bucket": {
            "name": "test-bucket"
        },
        "object": {
            "key": "myfile.json",
            "size": 1977111,
            "etag": "bd3be0765633550cd20efba81a18bdc8",
            "sequencer": "00641C71589DC414A8"
        },
        "request-id": "AKCNK2852W14P76M",
        "requester": "694977046108",
        "source-ip-address": "1.2.3.4",
        "reason": "PutObject"
    }

For contrast, if the Amazon Translate service sends the event when a translation job completes, the detail section of the event object is much simpler. It has only the job ID and the job status.

{
    "version": "0",
    "id": "5feba6e9-5804-d1e0-1f69-de25a5956440",
    "detail-type": "Translate TextTranslationJob State Change",
    "source": "aws.translate",
    "account": "694977046108",
    "time": "2023-03-23T14:48:58Z",
    "region": "us-east-1",
    "resources": [],
    "detail": {
        "jobId": "f3df31de5794a038bbe685611c6caa1c",
        "jobStatus": "COMPLETED"
    }
}

It is possible to create custom events, to pass between your applications and services, but that is beyond the scope of this post.

Event Buses

Event buses receive events from sources that emit events. The bus then delivers the events to targets. To continue the earlier example, when a file uploads to an S3 bucket, the S3 service emits an event to the event bus. When the event bus receives the event, it uses rules to determine which events should be sent to which targets.

A target is a destination for events. A single event can be sent to multiple targets. The target can be a Lambda function, an Amazon SQS queue, CloudWatch logs, etc.

You can have multiple event buses in your account. Your account will already have a “default” event bus, you will use the default one for this example.

Event rules

As mentioned previously, event rules are used to determine which events to send to which targets. A rule has two main parts: the event pattern and the target(s).

The event pattern is a JSON object that is used to match the events and determine which target to send an event to. The pattern can be very broad, or very specific. For example, to match all events emitted from S3, you can use the following event pattern.

{
  "source": ["aws.s3"]
}

Or you can refine the pattern to match S3 object created events, on a specific bucket, created by a specific IP address.

{
  "source": ["aws.s3"],
  "detail-type": ["Object Created"],
  "detail": {
    "bucket": {
      "name": ["my-test-bucket"]
    },
    "source-ip-address": ["1.2.3.4"]
  }
}

Now that you have a good understanding of the mechanics of EventBridge, let’s see how to use a trigger event to invoke a Lambda function when a file is uploaded to an S3 bucket.

Putting it together – Events, Buses, and Rules

In the following diagram, the S3 and Amazon Translate services both emit events to a default event bus. Rules configured for the default event bus determine which events are sent to which targets.

The targets receive the events and process them accordingly. In the example shown, the Lambda function will process the event through its event handler, and CloudWatch will log the events to its stream.

Amazon S3 and Amazon Translate events routed through EventBridge default bus and rules sending events to AWS Lambda function and CloudWatch Logs

Invoking a Lambda function when a file uploads to an S3 bucket

To keep this example simple, the Lambda function will log the S3 EventBridge event to CloudWatch logs. You will:

  1. Create an S3 bucket and enable EventBridge notification on that bucket.
  2. Create a Lambda function that handles S3 EventBridge events, and logs the events to CloudWatch logs.
  3. Create an EventBridge rule that sends S3 events to the Lambda function.

Getting the tools

You will use command line tools to create and deploy the Lambda function, and create the S3 bucket. These tools work on Windows, macOS, and Linux. Follow these steps to install the necessary tools.

  1. Get the AWS Extensions for .NET CLI:
    dotnet tool install -g Amazon.Lambda.Tools
  2. Get the .NET Lambda function templates:
    dotnet new --install Amazon.Lambda.Templates
  3. Get the latest version of the AWS CLI, and configure it for your account.

Creating the S3 bucket

You can use an existing S3 bucket, if that is your preference. Otherwise, create a new S3 bucket. Bucket names must be unique across all AWS accounts, not just yours. Note, you can’t use the name eventbridge-lambda-and-s3-example for your bucket, because it is already in use.

If you want your bucket to be in the us-east-1 region, use the following command:

aws s3api create-bucket --bucket eventbridge-lambda-and-s3-example

If you want your bucket to be in a different region, use the following command:

aws s3api create-bucket --bucket eventbridge-lambda-and-s3-example --create-bucket-configuration LocationConstraint=REGION

If the command is successful, you will see a message with the Location of the bucket:

{
  "Location": "..."
}

To allow the S3 bucket to send EventBridge notifications, use the following command:

aws s3api put-bucket-notification-configuration --bucket eventbridge-lambda-and-s3-example --notification-configuration '{ "EventBridgeConfiguration": {} }'

You can verify that the bucket is configured to send EventBridge notifications by using the following command:

aws s3api get-bucket-notification-configuration --bucket eventbridge-lambda-and-s3-example

You should see the following output:

{
  "EventBridgeConfiguration": {}
}

You can find documentation for all these commands at AWS CLI Command Reference.

Creating the Lambda function

From the command line run the following command to create a new .NET Lambda function:

dotnet new lambda.EmptyFunction --name EventBridgeLambdaAndS3Example

Change to the directory of the new project:

cd EventBridgeLambdaAndS3Example\src\EventBridgeLambdaAndS3Example

To handle S3 EventBridge events, you need to add the Amazon.Lambda.CloudWatchEvents NuGet package to the project:

dotnet add package Amazon.Lambda.CloudWatchEvents

If you are wondering why the package is called Amazon.Lambda.CloudWatchEvents, it is because CloudWatch Events is the predecessor of EventBridge.

Open the project in this directory in your favorite IDE.

Open the Function.cs file and replace the contents with the following code:

using Amazon.Lambda.Core;
using Amazon.Lambda.CloudWatchEvents.S3Events;
using System.Text.Json;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace EventBridgeLambdaAndS3Example;

public class Function
{
    public void FunctionHandler(S3ObjectCreateEvent s3ObjectCreateEvent, ILambdaContext context)
    {
        context.Logger.LogLine("S3 Object Create Event Received");
        context.Logger.LogLine(JsonSerializer.Serialize(s3ObjectCreateEvent));
    }
}

When the function handler is invoked, the Lambda function will log two lines to the CloudWatch logs. The first line will be the string S3 Object Create Event Received, the second line will be the JSON representation of the S3 EventBridge event.

Deploy the function using the following command:

dotnet lambda deploy-function EventBridgeLambdaAndS3Example

When prompted to select or create a role for the Lambda function, choose the option to create a new role. It will be the last number on the list.

Give the new role the name EventBridgeLambdaAndS3ExampleRole.

Attach a policy to the role. Choose AWSLambdaBasicExecutionRole, it is number 6 on the list. This will give the function permissions to write to CloudWatch logs.

Now that you have your Lambda function and S3 bucket, you can wire them up with an EventBridge rule.

Configuring EventBridge

Now you will configure EventBridge to send S3 events from your bucket to the Lambda function using the AWS Console.

Open https://console.aws.amazon.com/events/ in your browser and choose “Rules” in the left-hand navigation pane, and choose or click Create rule.

Amazon Event Bridge window where you can select an event bus, search for or create a rule.

This begins the process of creating a new EventBridge rule.

On the Define rule detail step, give the rule the name “EventBridgeLambdaAndS3Example“, and select the “default” event bus.

Choose Next when done.

Define rule detail window where you choose a rule name and event bus.

On the Build event pattern step, select AWS events or EventBridge partner events as the event source.

Build event pattern window where you select the event source and can select the sample event type.

You can skip over the “Sample event” and scroll down to the “Creation method” and “Event pattern” sections.

Here you have to fill in six fields:

  1. For the creation method, choose “Use pattern form“.
  2. For the event source, choose “AWS services“.
  3. For the AWS service, choose “Simple Storage Service (S3)“.
  4. For the event type, choose “Amazon S3 Event Notification“.
  5. Select “Specific event(s)”, and choose “Object Created“.
  6. Select “Specific bucket(s) by name”, and enter the name of your S3 bucket.

Build event pattern window where you select a creation method, and define the pattern information.

In the Event pattern window, you can see the JSON representation of the event pattern. It should look similar to this:

{
  "source": ["aws.s3"],
  "detail-type": ["Object Created"],
  "detail": {
    "bucket": {
      "name": ["eventbridge-lambda-and-s3-example"]
    }
  }
}

Choose Next when done.

On the Select target(s) step, choose AWS service as the target type. From the Select a target dropdown list, select Lambda function, and finally choose the function you created from the Function dropdown list.

Choose Next when done.

Select target window here you define the target types, select a target, and define a function.

You can skip the Configure tags step by choosing Next.

This is an optional step where you can configure tags for the rule by selecting Add new tag.

On the Review step, you can review the details of the rule. Choose Create rule when done.

The Review and create window where you can review the rule details and select Create rule to create the rule.

You will now be at the EventBridge Rules page with a message that your rule was created successfully. Your new rule is listed in the Rules section of the page.

Rules list window displaying the newly created rule.

Everything is in place now. Time to test out EventBridge!

Add a file to the S3 bucket

You can upload a file to the S3 bucket using the AWS Console, or the AWS Command Line Interface (CLI).

Create a file named “hello.txt” and add some text to it. Then upload it to S3 with this command:

aws s3 cp .\hello.txt s3://eventbridge-lambda-and-s3-example

Review the Lambda function

After you create the rule in EventBridge, return to your Lambda function in the AWS Console.

In the Function overview, choose the EventBridge trigger. This will open the Configuration tab where you see the EventBridge rule you created listed as a trigger for the function.

In this window review the Lambda triggers and view the newly created rule.

This confirms that the EventBridge rule has a trigger for the Lambda function.

View the CloudWatch log of the S3 event

To view the CloudWatch log generated by the Lambda function, go to the AWS Console, and open the Lambda function.

On the Monitor tab, choose View logs in CloudWatch.

The Lambda function example window where you can view the function Overview, logs, and access the CloudWatch logs.

This opens the CloudWatch logs for the function.

Open the most recent log stream.

Log group details window. You can select Log streams and view the log stream information.

Log events window displaying the log entries for the Lambda function.

Look for an entry with “S3 Object Create Event Received”. Immediately below that will be the JSON of the event object.

This confirms that uploading the file to S3 caused an event to be sent to EventBridge, which was then forwarded to the Lambda function, which logged the event to CloudWatch logs.

Cleaning up

It’s time to clean up the resources.

Delete the S3 object:

aws s3api delete-object --bucket eventbridge-lambda-and-s3-example --key Hello.txt

Delete the S3 bucket:

aws s3api delete-bucket --bucket eventbridge-lambda-and-s3-example

Delete the Lambda function:

dotnet lambda delete-function EventBridgeLambdaAndS3Example

Delete the EventBridge rule by opening EventBridge Rules in the AWS Console. Search for the rule you created, select It, and choose Delete. A confirmation box will pop up, confirm the deletion there.

Conclusion

In this post, you learned how to use EventBridge to route S3 EventBridge events to a Lambda function. This is a very simple example, but it will give you a good foundation for using EventBridge to route and use events within your AWS applications. Now that you understand how EventBridge works, try using it to connect other AWS services to your Lambda functions, or sending events to services such as AWS Step Functions, Amazon Kinesis, or and API Gateway. As you use and learn more about it, you will find more ways to use it!