{"id":27962621,"url":"https://github.com/ottaway-c/aws-dotnet-todo-api","last_synced_at":"2026-04-13T21:01:31.894Z","repository":{"id":198653293,"uuid":"690438922","full_name":"ottaway-c/aws-dotnet-todo-api","owner":"ottaway-c","description":"Sample Todo REST API built using: AWS CDK, Dynamo, Lambda and API Gateway","archived":false,"fork":false,"pushed_at":"2025-04-29T04:09:32.000Z","size":114,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"dev","last_synced_at":"2025-05-07T19:56:38.790Z","etag":null,"topics":["apigateway","aws","aws-cdk","cdk","cdk-examples","docker","dotnet","dynamodb","ecr","fast-endpoints","lambda","repr-pattern"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ottaway-c.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-09-12T07:43:11.000Z","updated_at":"2025-04-29T04:09:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"eda88678-11ff-4113-a755-4097d521962b","html_url":"https://github.com/ottaway-c/aws-dotnet-todo-api","commit_stats":null,"previous_names":["ottaway-c/aws-dotnet-todo-api"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ottaway-c%2Faws-dotnet-todo-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ottaway-c%2Faws-dotnet-todo-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ottaway-c%2Faws-dotnet-todo-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ottaway-c%2Faws-dotnet-todo-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ottaway-c","download_url":"https://codeload.github.com/ottaway-c/aws-dotnet-todo-api/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252949317,"owners_count":21830150,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apigateway","aws","aws-cdk","cdk","cdk-examples","docker","dotnet","dynamodb","ecr","fast-endpoints","lambda","repr-pattern"],"created_at":"2025-05-07T19:56:43.533Z","updated_at":"2026-04-13T21:01:31.888Z","avatar_url":"https://github.com/ottaway-c.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# aws-dotnet-todo-api\n\n## Overview\n\nA simple Todo REST API that leverages API Gateway, Lambda and DynamoDB.\n\n### Design considerations:\n\n-   The entire application is deployed as a container running in AWS Lambda.\n-   I opted to use the request, endpoint, response ([REPR](https://deviq.com/design-patterns/repr-design-pattern)) design pattern.\n-   Input must be validated validated using fluent validation.\n-   Endpoints should be easy to test.\n-   Structured logging using the Serilog logging library.\n\n### I have used the latest .NET language/compiler features such as:\n\n-   Nullable value types and use of the 'required' modifier for class properties.\n-   Compile time checking of potential null reference exceptions.\n-   Source generators for JSON and object mapping.\n\n### Infrastructure components\n\n-   AWS Lambda ⚡\n-   Elastic Container Repository (ECR)\n-   API Gateway\n-   DynamoDb\n\n### AWS CDK\n\nI utilised AWS CDK to provision the required API Gateway, DynamoDB table, ECR repository and Lambda function.\n\nAWS CDK was chosen for the following reasons:\n\n-   Type safety and code completion in your IDE of choice.\n-   Sensible defaults when provisioning resources.\n-   Easy to integrate with CI/CD such as GitHub Actions.\n-   Simplifies the granting of IAM permissions and enforces best practices.\n-   Ability to create more advanced infrastructure without having to write raw CloudFormation.\n\n### Testing Strategy\n\nI've followed a pretty standard approach for testing serverless applications:\n\n-   Unit tests — Anything that can be run in memory for example validators\n-   Integration tests — Test that the code functions correctly against real AWS infrastructure like DynamoDB.\n-   End to end tests — Test the full application usually against the actual HTTP API. This is important to make sure that IAM permissions have been setup correctly.\n\nFor more information about serverless testing I recommend [this blog post](https://theburningmonk.com/2022/05/my-testing-strategy-for-serverless-applications/).\n\n## Github Actions\n\nI have included the following Github Actions that run when creating PR’s into various branches:\n\n-   check.yml — Runs on pull requests to the dev branch. This is used to test feature branches. An ephemeral stack is stood up, and integration/e2e tests run against it.\n-   cleanup.yml — Runs when pull request to the dev branch are closed. Runs 'cdk destroy' to cleanup feature branch stacks.\n-   dev.yml — Runs when a pull request is merged to the dev branch. Deploys the stack to dev, and runs e2e tests.\n-   prod.yml — Runs when a pull request is merged to the main branch. Deploys the stack to prod, and runs e2e tests.\n\n## Prereqs\n\n-   Install VS Code for working in CDK in Typescript\n-   Install .Net 8 SDK https://dotnet.microsoft.com/en-us/download/dotnet/8.0\n-   Install Node.js 20 LTS https://nodejs.org/en/\n-   Install CDK cli tool globally https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html\n-   Install AWS cli tool https://aws.amazon.com/cli/ and setup default credentials using `aws configure`.\n\n## Install\n\nInstall CDK cli\n\n```\nnpm install -g aws-cdk\n```\n\nInstall cdk packages\n\n```\nnpm i\n```\n\nCreate a `.env` file and add the following variables:\n\n```\nAWS_REGION=\u003cAWS_REGION\u003e\nCDK_DEFAULT_ACCOUNT=\u003cAWS_ACCOUNT_ID\u003e\nCDK_DEFAULT_REGION=\u003cAWS_REGION\u003e\nSERVICE=todo-api\nSTAGE=1001 # This is your ticket/feature branch name like 1001. I also use stages for dev, uat and prod.\nTAG=0.0.1\n```\n\nCreate an instance profile called `todo-api`. Ensure that the account and region match the account and region declared in the envionment variables above.\n\n```\naws configure sso --profile todo-api\n```\n\n## Running locally\n\nI have set this up to run with Docker-Compose in Rider. It probably works in Visual Studio as well, but I haven't tried it.\n\n## Synth\n\nSynth is useful during development to test out changes you're making to CDK. It doesn't actually deploy anything, it just\nprints out the CloudFormation stack as YAML.\n\n```\naws sso login --profile todo-api\ncdk synth todo-api-feat-1008-app --profile todo-api\n```\n\n## Deploy\n\nStep 1: Refresh your AWS credentials\n\n```\nnpm run sso\n```\n\nStep 2: Deploy ECR stack\n\n```\ncdk deploy todo-api-feat-1008-ecr --profile todo-api\n```\n\nStep 3: Authenticate to ECR\n\n```\naws ecr get-login-password --profile todo-api | docker login --username AWS --password-stdin \u003cAWS_ACCOUNT_ID\u003e.dkr.ecr.\u003cAWS_REGION\u003e.amazonaws.com\n```\n\nStep 4: Build and push docker image\n\n```\nnpm run build\nnpm run push\n```\n\n**Note:**\n\nIf you make changes to the code locally and wish to deploy the changes to an existing stack, bump the version number assigned to the `TAG` environment variable. E.g\n\n```\nTAG=0.0.2 # Increase this version number by 1\n```\n\nStep 5: Deploy\n\n```\ncdk deploy todo-api-feat-1008-app --profile todo-api\n```\n\n## Test\n\n```\nnpm run sso\nnpm run unit\nnpm run integration\nnpm run e2e\n```\n\n## Destroy\n\n**Note:**\n\nAll stack resources have been created with a `RemovalPolicy.DESTROY`. This is to ensure a clean teardown when the stack is deleted. In a production scenario, non-ephemeral resources such as DynamoDb tables should be set to `RemovalPolicy.SNAPSHOT` or `RemovalPolicy.RETAIN`.\n\n```\nnpm run sso\ncdk destroy todo-api-feat-1008-app --profile todo-api\ncdk destroy todo-api-feat-1008-ecr --profile todo-api\n```\n\n## Dotnet Tools\n\nI am using DotNet Format to format C# code\n\nInstall DotNet Format and Kiota\n\n```\ndotnet tool restore\n```\n\nUpgrading Kiota\n\n```\ndotnet tool update microsoft.openapi.kiota\n```\n\nUpgrading DotNet Format\n\n```\ndotnet tool update dotnet-format\n```\n\nRun formatter\n\n```\nnpm run format\n```\n\n## API Client Generation\n\nI am generating the C# API client using code generation.\n\nRun the following command to build a client:\n\n```\nnpm run gen-client\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fottaway-c%2Faws-dotnet-todo-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fottaway-c%2Faws-dotnet-todo-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fottaway-c%2Faws-dotnet-todo-api/lists"}