DynamoDb, Reading and Writing Data with .Net Core - Part 1

Want to learn more about AWS Lambda and .NET? Check out my A Cloud Guru course on ASP.NET Web API and Lambda.

Full source code available here.

A few weeks ago I started playing with DynamoDb in a .NET application. I read through the AWS documentation but felt it was incomplete and a little out of date. This made it quite hard to figure out the “right” way of using the AWS DynamoDb libraries. For example, there is no good example of using dependency injection to pass a DynamoDb client into a controller, and no guidance on whether that client should be request, transient, or, singleton scoped.

In this and the following posts I’m going to describe approaches that work, they may not be “right” either. This post is will show how to read and write from DynamoDb using the document interface and pass in IAmazonDynamoDB to the controller. By default, this is singleton scoped.

Getting Started

Getting started with AWS can feel like a bit of a hurdle (especially due to credential complications), and a good way to get your feet wet is to use localstack – https://github.com/localstack/localstack, consider installing https://github.com/localstack/awscli-local too.

I’m not going to describe how to get localstack running, I’m going to assume you have done that or you have an AWS account and you know how to set up the required credentials.

Once you have localstack installed or your AWS account working, run the following to create the DynamoDb table.

aws --endpoint-url=http://localhost:4569 dynamodb create-table --table-name People --attribute-definitions AttributeName=PersonId,AttributeType=N --key-schema AttributeName=PersonId,KeyType=HASH --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1

You can add data to the table with the following -

1aws --endpoint-url=http://localhost:4569 dynamodb put-item --table-name People --item '{"PersonId":{"N":"1"},"State":{"S":"MA"}, "FirstName": {"S":"Alice"}, "LastName": {"S":"Andrews"}}'
2aws --endpoint-url=http://localhost:4569 dynamodb put-item --table-name People --item '{"PersonId":{"N":"2"},"State":{"S":"MA"}, "FirstName": {"S":"Ben"}, "LastName": {"S":"Bradley"}}'
3aws --endpoint-url=http://localhost:4569 dynamodb put-item --table-name People --item '{"PersonId":{"N":"3"},"State":{"S":"MA"}, "FirstName": {"S":"Colin"}, "LastName": {"S":"Connor"}}'

To see all the items you just stored -

aws --endpoint-url=http://localhost:4569 dynamodb scan --table-name People

The Web API application

I’m going to show you how to retrieve an item by an id and to store a new item using the document interface, in the next post I’ll show how to do the same with the object interface.

But first things first, configuration.

Open the appsettings.json file and replace what’s there with -

1{
2  "AWS": {
3    "Profile": "localstack-test-profile",
4    "Region": "us-east-1",
5    "ServiceURL": "http://localhost:4566"
6  }
7}
If you are connecting to the real AWS, you should remove the “ServiceURL”.

Add the AWSSDK.DynamoDBv2 NuGet package to the project.

In Startup.cs add a using Amazon.DynamoDBv2;

In ConfigureServices() add the following -

1public void ConfigureServices(IServiceCollection services)
2{
3    var awsOptions = Configuration.GetAWSOptions();
4
5    services.AddDefaultAWSOptions(awsOptions);
6    services.AddAWSService<IAmazonDynamoDB>();
7    services.AddControllers();
8}

Inside the controller, I use IAmazonDynamoDB to execute calls against DynamoDb.

 1//snip...
 2using Amazon.DynamoDBv2;
 3using Amazon.DynamoDBv2.DocumentModel;
 4//snip.. 
 5
 6public class PersonController : ControllerBase
 7{
 8    private readonly IAmazonDynamoDB _amazonDynamoDB;
 9    public PersonController(IAmazonDynamoDB amazonDynamoDB)
10    {   
11        _amazonDynamoDB = amazonDynamoDB;
12    }
13    //snip..

Here is how to get an item from the People table.

1[HttpGet("{personId}")]
2public async Task<IActionResult> Get(int personId)
3{
4    Table people = Table.LoadTable(_amazonDynamoDB, "People");
5    var person =  JsonSerializer.Deserialize<Person> ((await people.GetItemAsync(personId)).ToJson());
6    return Ok(person);
7}

This is how you add an item to the People table.

 1[HttpPost]
 2public async Task<IActionResult> Post(Person person)
 3{
 4    Table people = Table.LoadTable(_amazonDynamoDB, "People");
 5    
 6    var document = new Document();
 7    document["PersonId"] = person.PersonId;
 8    document["State"] = person.State;
 9    document["FirstName"] = person.FirstName;
10    document["LastName"] = person.LastName;
11    await people.PutItemAsync(document);
12    
13    return Created("", document.ToJson());
14}

I’m not a fan of all the hard-coded attributes for properties of the person, but this is a way of doing it. Another approach is to use the object model, and I’ll show that in a later blog post.

To exercise the GET method open your browser and go to http://localhost:5000/people/1.

To exercise the POST you can use Fiddler, Curl, Postman, or the very nice REST Client extension for Visual Studio Code.

If you are using that extension, here is the request -

POST http://localhost:5000/person HTTP/1.1
content-type: application/json

{
    "personId": 6,
    "state": "MA",
    "firstName": "Frank",
    "lastName" : "Freeley"
}

Full source code available here.

comments powered by Disqus

Related