├── LambdaApiSolution
├── src
│ ├── LambdaApiSolution
│ │ ├── GlobalSuppressions.cs
│ │ ├── Program.cs
│ │ ├── Constants.cs
│ │ ├── SolutionStage.cs
│ │ ├── LambdaApiSolution.csproj
│ │ ├── LambdaApiSolutionStack.cs
│ │ └── PipelineStack.cs
│ ├── LambdaApiSolution.DockerFunction
│ │ ├── test
│ │ │ └── LambdaApiSolution.DockerFunction.Tests
│ │ │ │ ├── FunctionTest.cs
│ │ │ │ └── LambdaApiSolution.DockerFunction.Tests.csproj
│ │ └── src
│ │ │ └── LambdaApiSolution.DockerFunction
│ │ │ ├── LambdaApiSolution.DockerFunction.csproj
│ │ │ ├── aws-lambda-tools-defaults.json
│ │ │ ├── Function.cs
│ │ │ ├── Dockerfile
│ │ │ └── Readme.md
│ ├── LambdaApiSolution.sln
│ └── .editorconfig
├── cdk.json
├── README.md
└── .gitignore
├── LICENSE
├── .gitignore
└── README.md
/LambdaApiSolution/src/LambdaApiSolution/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | [assembly:
2 | System.Diagnostics.CodeAnalysis.SuppressMessage("Potential Code Quality Issues",
3 | "RECS0026:Possible unassigned object created by 'new'",
4 | Justification = "Constructs add themselves to the scope in which they are created")]
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution/Program.cs:
--------------------------------------------------------------------------------
1 | using Amazon.CDK;
2 |
3 | namespace LambdaApiSolution
4 | {
5 | sealed class Program
6 | {
7 | public static void Main(string[] args)
8 | {
9 | App app = new App();
10 | PipelineStack pipelineStack = new PipelineStack(app, "LambdaApiSolutionPipelineStack");
11 | app.Synth();
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution/Constants.cs:
--------------------------------------------------------------------------------
1 | namespace LambdaApiSolution
2 | {
3 | public static class Constants
4 | {
5 | public static string Branch = "main";
6 | public static string GitHubTokenSecretsManagerId = "GitHub-Token";
7 | public static string Owner = "scottenriquez";
8 | public static string RepositoryName = "dotnet-5-lambda-api-cdk";
9 | }
10 | }
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution/SolutionStage.cs:
--------------------------------------------------------------------------------
1 | using Amazon.CDK;
2 | using Construct = Constructs.Construct;
3 |
4 | namespace LambdaApiSolution
5 | {
6 | public class SolutionStage : Stage
7 | {
8 | public SolutionStage(Construct scope, string id, IStageProps props = null) : base(scope, id, props)
9 | {
10 | LambdaApiSolutionStack lambdaApiSolutionStack = new LambdaApiSolutionStack(this, "Solution");
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/LambdaApiSolution/cdk.json:
--------------------------------------------------------------------------------
1 | {
2 | "app": "dotnet run -p src/LambdaApiSolution/LambdaApiSolution.csproj",
3 | "context": {
4 | "@aws-cdk/core:enableStackNameDuplicates": "true",
5 | "aws-cdk:enableDiffNoFail": "true",
6 | "@aws-cdk/core:newStyleStackSynthesis": "true",
7 | "@aws-cdk/core:stackRelativeExports": "true",
8 | "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true,
9 | "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true,
10 | "@aws-cdk/aws-kms:defaultKeyPolicies": true,
11 | "@aws-cdk/aws-s3:grantWriteWithoutAcl": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/LambdaApiSolution/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to your CDK C# project!
2 |
3 | This is a blank project for C# development with CDK.
4 |
5 | The `cdk.json` file tells the CDK Toolkit how to execute your app.
6 |
7 | It uses the [.NET Core CLI](https://docs.microsoft.com/dotnet/articles/core/) to compile and execute your project.
8 |
9 | ## Useful commands
10 |
11 | * `dotnet build src` compile this app
12 | * `cdk deploy` deploy this stack to your default AWS account/region
13 | * `cdk diff` compare deployed stack with current state
14 | * `cdk synth` emits the synthesized CloudFormation template
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution.DockerFunction/test/LambdaApiSolution.DockerFunction.Tests/FunctionTest.cs:
--------------------------------------------------------------------------------
1 | using Amazon.Lambda.APIGatewayEvents;
2 | using Xunit;
3 | using Amazon.Lambda.TestUtilities;
4 |
5 | namespace LambdaApiSolution.DockerFunction.Tests
6 | {
7 | public class FunctionTest
8 | {
9 | [Fact]
10 | public void TestToUpperFunction()
11 | {
12 | Function function = new Function();
13 | TestLambdaContext context = new TestLambdaContext();
14 | APIGatewayProxyRequest apiGatewayProxyRequest = new APIGatewayProxyRequest()
15 | {
16 | Body = "hello world"
17 | };
18 | Casing casing = function.FunctionHandler(apiGatewayProxyRequest, context);
19 | Assert.Equal("hello world", casing.Lower);
20 | Assert.Equal("HELLO WORLD", casing.Upper);
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution.DockerFunction/test/LambdaApiSolution.DockerFunction.Tests/LambdaApiSolution.DockerFunction.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net5.0
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution.DockerFunction/src/LambdaApiSolution.DockerFunction/LambdaApiSolution.DockerFunction.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net5.0
4 | true
5 | Lambda
6 |
7 |
8 | true
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution.DockerFunction/src/LambdaApiSolution.DockerFunction/aws-lambda-tools-defaults.json:
--------------------------------------------------------------------------------
1 | {
2 | "Information": [
3 | "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
4 | "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
5 | "dotnet lambda help",
6 | "All the command line options for the Lambda command can be specified in this file."
7 | ],
8 | "profile": "",
9 | "region": "",
10 | "configuration": "Release",
11 | "package-type": "image",
12 | "function-memory-size": 256,
13 | "function-timeout": 30,
14 | "image-command": "LambdaApiSolution.DockerFunction::LambdaApiSolution.DockerFunction.Function::FunctionHandler",
15 | "docker-host-build-output-dir": "./bin/Release/net5.0/linux-x64/publish"
16 | }
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution.DockerFunction/src/LambdaApiSolution.DockerFunction/Function.cs:
--------------------------------------------------------------------------------
1 | using Amazon.Lambda.APIGatewayEvents;
2 | using Amazon.Lambda.Core;
3 |
4 | // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
5 | [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
6 |
7 | namespace LambdaApiSolution.DockerFunction
8 | {
9 | public class Function
10 | {
11 | ///
12 | /// A simple function that takes a string and returns both the upper and lower case version of the string.
13 | ///
14 | ///
15 | ///
16 | ///
17 | public Casing FunctionHandler(APIGatewayProxyRequest apiGatewayProxyRequest, ILambdaContext context)
18 | {
19 | string input = apiGatewayProxyRequest.Body;
20 | return new Casing(input.ToLower(), input.ToUpper());
21 | }
22 | }
23 |
24 | public record Casing(string Lower, string Upper);
25 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Scottie Enriquez
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution.DockerFunction/src/LambdaApiSolution.DockerFunction/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM public.ecr.aws/lambda/dotnet:5.0
2 | FROM mcr.microsoft.com/dotnet/sdk:5.0 as build-image
3 |
4 | ARG FUNCTION_DIR="/build"
5 | ARG CONFIGURATION="release"
6 | ENV PATH="/root/.dotnet/tools:${PATH}"
7 |
8 | RUN apt-get update && apt-get -y install zip
9 |
10 | RUN mkdir $FUNCTION_DIR
11 | WORKDIR $FUNCTION_DIR
12 | COPY Function.cs LambdaApiSolution.DockerFunction.csproj aws-lambda-tools-defaults.json $FUNCTION_DIR/
13 | RUN dotnet tool install -g Amazon.Lambda.Tools
14 |
15 | RUN mkdir -p build_artifacts
16 | RUN if [ "$CONFIGURATION" = "debug" ]; then dotnet lambda package --configuration Debug --package-type zip; else dotnet lambda package --configuration Release --package-type zip; fi
17 | RUN if [ "$CONFIGURATION" = "debug" ]; then cp -r /build/bin/Debug/net5.0/publish/* /build/build_artifacts; else cp -r /build/bin/Release/net5.0/publish/* /build/build_artifacts; fi
18 |
19 | FROM public.ecr.aws/lambda/dotnet:5.0
20 |
21 | COPY --from=build-image /build/build_artifacts/ /var/task/
22 | CMD ["LambdaApiSolution.DockerFunction::LambdaApiSolution.DockerFunction.Function::FunctionHandler"]
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution/LambdaApiSolution.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net5.0
6 |
7 | Major
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution/LambdaApiSolutionStack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Amazon.CDK;
3 | using Amazon.CDK.AWS.APIGatewayv2;
4 | using Amazon.CDK.AWS.APIGatewayv2.Integrations;
5 | using Amazon.CDK.AWS.Lambda;
6 |
7 | namespace LambdaApiSolution
8 | {
9 | public class LambdaApiSolutionStack : Stack
10 | {
11 | internal LambdaApiSolutionStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
12 | {
13 | DockerImageCode dockerImageCode =
14 | DockerImageCode.FromImageAsset("src/LambdaApiSolution.DockerFunction/src/LambdaApiSolution.DockerFunction");
15 | DockerImageFunction dockerImageFunction = new DockerImageFunction(this, "LambdaFunction",
16 | new DockerImageFunctionProps()
17 | {
18 | Code = dockerImageCode,
19 | Description = ".NET 5 Docker Lambda function"
20 | });
21 | HttpApi httpApi = new HttpApi(this, "APIGatewayForLambda", new HttpApiProps()
22 | {
23 | ApiName = "APIGatewayForLambda",
24 | CreateDefaultStage = true,
25 | CorsPreflight = new CorsPreflightOptions()
26 | {
27 | AllowMethods = new[] {HttpMethod.GET},
28 | AllowOrigins = new[] {"*"},
29 | MaxAge = Duration.Days(10)
30 | }
31 | });
32 | LambdaProxyIntegration lambdaProxyIntegration = new LambdaProxyIntegration(new LambdaProxyIntegrationProps()
33 | {
34 | Handler = dockerImageFunction,
35 | PayloadFormatVersion = PayloadFormatVersion.VERSION_2_0
36 | });
37 | httpApi.AddRoutes(new AddRoutesOptions()
38 | {
39 | Path = "/casing",
40 | Integration = lambdaProxyIntegration,
41 | Methods = new[] {HttpMethod.POST}
42 | });
43 | string guid = Guid.NewGuid().ToString();
44 | CfnOutput apiUrl = new CfnOutput(this, "APIGatewayURLOutput", new CfnOutputProps()
45 | {
46 | ExportName = $"APIGatewayEndpointURL-{guid}",
47 | Value = httpApi.ApiEndpoint
48 | });
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution/PipelineStack.cs:
--------------------------------------------------------------------------------
1 | using Amazon.CDK;
2 | using Amazon.CDK.AWS.CodeBuild;
3 | using Amazon.CDK.AWS.CodePipeline;
4 | using Amazon.CDK.AWS.CodePipeline.Actions;
5 | using Amazon.CDK.Pipelines;
6 |
7 | namespace LambdaApiSolution
8 | {
9 | public class PipelineStack : Stack
10 | {
11 | internal PipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
12 | {
13 | Artifact_ sourceArtifact = new Artifact_();
14 | Artifact_ cloudAssemblyArtifact = new Artifact_();
15 | CdkPipeline pipeline = new CdkPipeline(this, "LambdaApiSolutionPipeline", new CdkPipelineProps()
16 | {
17 | CloudAssemblyArtifact = cloudAssemblyArtifact,
18 | PipelineName = "LambdaApiSolutionPipeline",
19 | SourceAction = new GitHubSourceAction(new GitHubSourceActionProps()
20 | {
21 | ActionName = "GitHubSource",
22 | Output = sourceArtifact,
23 | OauthToken = SecretValue.SecretsManager(Constants.GitHubTokenSecretsManagerId),
24 | Owner = Constants.Owner,
25 | Repo = Constants.RepositoryName,
26 | Branch = Constants.Branch,
27 | Trigger = GitHubTrigger.POLL
28 | }),
29 | SynthAction = new SimpleSynthAction(new SimpleSynthActionProps()
30 | {
31 | Environment = new BuildEnvironment
32 | {
33 | // required for .NET 5
34 | // https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
35 | BuildImage = LinuxBuildImage.STANDARD_5_0
36 | },
37 | SourceArtifact = sourceArtifact,
38 | CloudAssemblyArtifact = cloudAssemblyArtifact,
39 | Subdirectory = "LambdaApiSolution",
40 | InstallCommands = new[] {"npm install -g aws-cdk"},
41 | BuildCommands = new[] {"dotnet build src/LambdaApiSolution.sln"},
42 | SynthCommand = "cdk synth"
43 | })
44 | });
45 | CdkStage developmentStage = pipeline.AddApplicationStage(new SolutionStage(this, "Development"));
46 | CdkStage testStage = pipeline.AddApplicationStage(new SolutionStage(this, "Test"));
47 | testStage.AddManualApprovalAction(new AddManualApprovalOptions() {ActionName = "PromoteToProduction"});
48 | CdkStage productionStage = pipeline.AddApplicationStage(new SolutionStage(this, "Production"));
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution.DockerFunction/src/LambdaApiSolution.DockerFunction/Readme.md:
--------------------------------------------------------------------------------
1 | # AWS Lambda Empty Docker Image Function Project
2 |
3 | This starter project consists of:
4 | * Function.cs - Class file containing a class with a single function handler method
5 | * Dockerfile - Used with the `docker build` command to build the docker image
6 | * aws-lambda-tools-defaults.json - default argument settings for use within Visual Studio and command line deployment tools for AWS
7 |
8 | You may also have a test project depending on the options selected.
9 |
10 | ## Packaging as a Docker image.
11 |
12 | This project is configured to package the Lambda function as a Docker image. The default configuration for the project and the Dockerfile is to build
13 | the .NET project on the host machine and then execute the `docker build` command which copies the .NET build artifacts from the host machine into
14 | the Docker image.
15 |
16 | The `--docker-host-build-output-dir` switch, which is set in the `aws-lambda-tools-defaults.json`, triggers the
17 | AWS .NET Lambda tooling to build the .NET project into the directory indicated by `--docker-host-build-output-dir`. The Dockerfile
18 | has a **COPY** command which copies the value from the directory pointed to by `--docker-host-build-output-dir` to the `/var/task` directory inside of the
19 | image.
20 |
21 | Alternatively the Docker file could be written to use [multi-stage](https://docs.docker.com/develop/develop-images/multistage-build/) builds and
22 | have the .NET project built inside the container. Below is an example of building .NET 5 project inside the image.
23 |
24 | ```dockerfile
25 | FROM ecr.aws/lambda/dotnet:5.0 AS base
26 |
27 | FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim as build
28 | WORKDIR /src
29 | COPY ["BlueprintBaseName.csproj", "BlueprintBaseName/"]
30 | RUN dotnet restore "BlueprintBaseName/BlueprintBaseName.csproj"
31 |
32 | WORKDIR "/src/BlueprintBaseName"
33 | COPY . .
34 | RUN dotnet build "BlueprintBaseName.csproj" --configuration Release --output /app/build
35 |
36 | FROM build AS publish
37 | RUN dotnet publish "BlueprintBaseName.csproj" \
38 | --configuration Release \
39 | --runtime linux-x64 \
40 | --self-contained false \
41 | --output /app/publish \
42 | -p:PublishReadyToRun=true
43 |
44 | FROM base AS final
45 | WORKDIR /var/task
46 | COPY --from=publish /app/publish .
47 | ```
48 |
49 | When building the .NET project inside the image you must be sure to copy all of the class libraries the .NET Lambda project is depending on
50 | as well before the `dotnet build` step. The final published artifacts of the .NET project must be copied to the `/var/task` directory.
51 | The `--docker-host-build-output-dir` switch can also be removed from the `aws-lambda-tools-defaults.json` to avoid the
52 | .NET project from being built on the host machine before calling `docker build`.
53 |
54 |
55 |
56 | ## Here are some steps to follow from Visual Studio:
57 |
58 | To deploy your function to AWS Lambda, right click the project in Solution Explorer and select *Publish to AWS Lambda*.
59 |
60 | To view your deployed function open its Function View window by double-clicking the function name shown beneath the AWS Lambda node in the AWS Explorer tree.
61 |
62 | To perform testing against your deployed function use the Test Invoke tab in the opened Function View window.
63 |
64 | To configure event sources for your deployed function, for example to have your function invoked when an object is created in an Amazon S3 bucket, use the Event Sources tab in the opened Function View window.
65 |
66 | To update the runtime configuration of your deployed function use the Configuration tab in the opened Function View window.
67 |
68 | To view execution logs of invocations of your function use the Logs tab in the opened Function View window.
69 |
70 | ## Here are some steps to follow to get started from the command line:
71 |
72 | You can deploy your application using the [Amazon.Lambda.Tools Global Tool](https://github.com/aws/aws-extensions-for-dotnet-cli#aws-lambda-amazonlambdatools) from the command line. Lambda function packaged as a Docker image require version 5.0.0 or later.
73 |
74 | Install Amazon.Lambda.Tools Global Tools if not already installed.
75 | ```
76 | dotnet tool install -g Amazon.Lambda.Tools
77 | ```
78 |
79 | If already installed check if new version is available.
80 | ```
81 | dotnet tool update -g Amazon.Lambda.Tools
82 | ```
83 |
84 | Execute unit tests
85 | ```
86 | cd "BlueprintBaseName/test/BlueprintBaseName.Tests"
87 | dotnet test
88 | ```
89 |
90 | Deploy function to AWS Lambda
91 | ```
92 | cd "BlueprintBaseName/src/BlueprintBaseName"
93 | dotnet lambda deploy-function
94 | ```
95 |
--------------------------------------------------------------------------------
/LambdaApiSolution/src/LambdaApiSolution.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LambdaApiSolution", "LambdaApiSolution\LambdaApiSolution.csproj", "{7137D01D-9950-4D3E-8810-DA18A0B40501}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LambdaApiSolution.DockerFunction", "LambdaApiSolution.DockerFunction", "{78E7694F-C460-44A4-9676-AC310A00C92E}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{07EA4852-483D-4CFC-877C-BE044766EB79}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LambdaApiSolution.DockerFunction", "LambdaApiSolution.DockerFunction\src\LambdaApiSolution.DockerFunction\LambdaApiSolution.DockerFunction.csproj", "{597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{B96957D2-DBAC-4F92-B7C9-5F403324B54B}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LambdaApiSolution.DockerFunction.Tests", "LambdaApiSolution.DockerFunction\test\LambdaApiSolution.DockerFunction.Tests\LambdaApiSolution.DockerFunction.Tests.csproj", "{CD8FCD6C-4A3C-41B0-A49B-589620E39454}"
17 | EndProject
18 | Global
19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 | Debug|Any CPU = Debug|Any CPU
21 | Debug|x64 = Debug|x64
22 | Debug|x86 = Debug|x86
23 | Release|Any CPU = Release|Any CPU
24 | Release|x64 = Release|x64
25 | Release|x86 = Release|x86
26 | EndGlobalSection
27 | GlobalSection(SolutionProperties) = preSolution
28 | HideSolutionNode = FALSE
29 | EndGlobalSection
30 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
31 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Debug|Any CPU.Build.0 = Debug|Any CPU
33 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Debug|x64.ActiveCfg = Debug|Any CPU
34 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Debug|x64.Build.0 = Debug|Any CPU
35 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Debug|x86.ActiveCfg = Debug|Any CPU
36 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Debug|x86.Build.0 = Debug|Any CPU
37 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Release|Any CPU.Build.0 = Release|Any CPU
39 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Release|x64.ActiveCfg = Release|Any CPU
40 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Release|x64.Build.0 = Release|Any CPU
41 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Release|x86.ActiveCfg = Release|Any CPU
42 | {7137D01D-9950-4D3E-8810-DA18A0B40501}.Release|x86.Build.0 = Release|Any CPU
43 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Debug|x64.ActiveCfg = Debug|Any CPU
46 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Debug|x64.Build.0 = Debug|Any CPU
47 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Debug|x86.ActiveCfg = Debug|Any CPU
48 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Debug|x86.Build.0 = Debug|Any CPU
49 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Release|Any CPU.Build.0 = Release|Any CPU
51 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Release|x64.ActiveCfg = Release|Any CPU
52 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Release|x64.Build.0 = Release|Any CPU
53 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Release|x86.ActiveCfg = Release|Any CPU
54 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5}.Release|x86.Build.0 = Release|Any CPU
55 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
56 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Debug|Any CPU.Build.0 = Debug|Any CPU
57 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Debug|x64.ActiveCfg = Debug|Any CPU
58 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Debug|x64.Build.0 = Debug|Any CPU
59 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Debug|x86.ActiveCfg = Debug|Any CPU
60 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Debug|x86.Build.0 = Debug|Any CPU
61 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Release|Any CPU.ActiveCfg = Release|Any CPU
62 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Release|Any CPU.Build.0 = Release|Any CPU
63 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Release|x64.ActiveCfg = Release|Any CPU
64 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Release|x64.Build.0 = Release|Any CPU
65 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Release|x86.ActiveCfg = Release|Any CPU
66 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454}.Release|x86.Build.0 = Release|Any CPU
67 | EndGlobalSection
68 | GlobalSection(NestedProjects) = preSolution
69 | {07EA4852-483D-4CFC-877C-BE044766EB79} = {78E7694F-C460-44A4-9676-AC310A00C92E}
70 | {597344E4-EAF7-4E2C-80B8-3FE6FD7F9FE5} = {07EA4852-483D-4CFC-877C-BE044766EB79}
71 | {B96957D2-DBAC-4F92-B7C9-5F403324B54B} = {78E7694F-C460-44A4-9676-AC310A00C92E}
72 | {CD8FCD6C-4A3C-41B0-A49B-589620E39454} = {B96957D2-DBAC-4F92-B7C9-5F403324B54B}
73 | EndGlobalSection
74 | EndGlobal
75 |
--------------------------------------------------------------------------------
/LambdaApiSolution/.gitignore:
--------------------------------------------------------------------------------
1 | # CDK asset staging directory
2 | .cdk.staging
3 | cdk.out
4 |
5 | # Created by https://www.gitignore.io/api/csharp
6 |
7 | ### Csharp ###
8 | ## Ignore Visual Studio temporary files, build results, and
9 | ## files generated by popular Visual Studio add-ons.
10 | ##
11 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
12 |
13 | # User-specific files
14 | *.suo
15 | *.user
16 | *.userosscache
17 | *.sln.docstates
18 |
19 | # User-specific files (MonoDevelop/Xamarin Studio)
20 | *.userprefs
21 |
22 | # Build results
23 | [Dd]ebug/
24 | [Dd]ebugPublic/
25 | [Rr]elease/
26 | [Rr]eleases/
27 | x64/
28 | x86/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUNIT
47 | *.VisualState.xml
48 | TestResult.xml
49 |
50 | # Build Results of an ATL Project
51 | [Dd]ebugPS/
52 | [Rr]eleasePS/
53 | dlldata.c
54 |
55 | # Benchmark Results
56 | BenchmarkDotNet.Artifacts/
57 |
58 | # .NET Core
59 | project.lock.json
60 | project.fragment.lock.json
61 | artifacts/
62 |
63 | # StyleCop
64 | StyleCopReport.xml
65 |
66 | # Files built by Visual Studio
67 | *_i.c
68 | *_p.c
69 | *_i.h
70 | *.ilk
71 | *.meta
72 | *.obj
73 | *.iobj
74 | *.pch
75 | *.pdb
76 | *.ipdb
77 | *.pgc
78 | *.pgd
79 | *.rsp
80 | *.sbr
81 | *.tlb
82 | *.tli
83 | *.tlh
84 | *.tmp
85 | *.tmp_proj
86 | *.log
87 | *.vspscc
88 | *.vssscc
89 | .builds
90 | *.pidb
91 | *.svclog
92 | *.scc
93 |
94 | # Chutzpah Test files
95 | _Chutzpah*
96 |
97 | # Visual C++ cache files
98 | ipch/
99 | *.aps
100 | *.ncb
101 | *.opendb
102 | *.opensdf
103 | *.sdf
104 | *.cachefile
105 | *.VC.db
106 | *.VC.VC.opendb
107 |
108 | # Visual Studio profiler
109 | *.psess
110 | *.vsp
111 | *.vspx
112 | *.sap
113 |
114 | # Visual Studio Trace Files
115 | *.e2e
116 |
117 | # TFS 2012 Local Workspace
118 | $tf/
119 |
120 | # Guidance Automation Toolkit
121 | *.gpState
122 |
123 | # ReSharper is a .NET coding add-in
124 | _ReSharper*/
125 | *.[Rr]e[Ss]harper
126 | *.DotSettings.user
127 |
128 | # JustCode is a .NET coding add-in
129 | .JustCode
130 |
131 | # TeamCity is a build add-in
132 | _TeamCity*
133 |
134 | # DotCover is a Code Coverage Tool
135 | *.dotCover
136 |
137 | # AxoCover is a Code Coverage Tool
138 | .axoCover/*
139 | !.axoCover/settings.json
140 |
141 | # Visual Studio code coverage results
142 | *.coverage
143 | *.coveragexml
144 |
145 | # NCrunch
146 | _NCrunch_*
147 | .*crunch*.local.xml
148 | nCrunchTemp_*
149 |
150 | # MightyMoose
151 | *.mm.*
152 | AutoTest.Net/
153 |
154 | # Web workbench (sass)
155 | .sass-cache/
156 |
157 | # Installshield output folder
158 | [Ee]xpress/
159 |
160 | # DocProject is a documentation generator add-in
161 | DocProject/buildhelp/
162 | DocProject/Help/*.HxT
163 | DocProject/Help/*.HxC
164 | DocProject/Help/*.hhc
165 | DocProject/Help/*.hhk
166 | DocProject/Help/*.hhp
167 | DocProject/Help/Html2
168 | DocProject/Help/html
169 |
170 | # Click-Once directory
171 | publish/
172 |
173 | # Publish Web Output
174 | *.[Pp]ublish.xml
175 | *.azurePubxml
176 | # Note: Comment the next line if you want to checkin your web deploy settings,
177 | # but database connection strings (with potential passwords) will be unencrypted
178 | *.pubxml
179 | *.publishproj
180 |
181 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
182 | # checkin your Azure Web App publish settings, but sensitive information contained
183 | # in these scripts will be unencrypted
184 | PublishScripts/
185 |
186 | # NuGet Packages
187 | *.nupkg
188 | # The packages folder can be ignored because of Package Restore
189 | **/[Pp]ackages/*
190 | # except build/, which is used as an MSBuild target.
191 | !**/[Pp]ackages/build/
192 | # Uncomment if necessary however generally it will be regenerated when needed
193 | #!**/[Pp]ackages/repositories.config
194 | # NuGet v3's project.json files produces more ignorable files
195 | *.nuget.props
196 | *.nuget.targets
197 |
198 | # Microsoft Azure Build Output
199 | csx/
200 | *.build.csdef
201 |
202 | # Microsoft Azure Emulator
203 | ecf/
204 | rcf/
205 |
206 | # Windows Store app package directories and files
207 | AppPackages/
208 | BundleArtifacts/
209 | Package.StoreAssociation.xml
210 | _pkginfo.txt
211 | *.appx
212 |
213 | # Visual Studio cache files
214 | # files ending in .cache can be ignored
215 | *.[Cc]ache
216 | # but keep track of directories ending in .cache
217 | !*.[Cc]ache/
218 |
219 | # Others
220 | ClientBin/
221 | ~$*
222 | *~
223 | *.dbmdl
224 | *.dbproj.schemaview
225 | *.jfm
226 | *.pfx
227 | *.publishsettings
228 | orleans.codegen.cs
229 |
230 | # Including strong name files can present a security risk
231 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
232 | #*.snk
233 |
234 | # Since there are multiple workflows, uncomment next line to ignore bower_components
235 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
236 | #bower_components/
237 |
238 | # RIA/Silverlight projects
239 | Generated_Code/
240 |
241 | # Backup & report files from converting an old project file
242 | # to a newer Visual Studio version. Backup files are not needed,
243 | # because we have git ;-)
244 | _UpgradeReport_Files/
245 | Backup*/
246 | UpgradeLog*.XML
247 | UpgradeLog*.htm
248 | ServiceFabricBackup/
249 | *.rptproj.bak
250 |
251 | # SQL Server files
252 | *.mdf
253 | *.ldf
254 | *.ndf
255 |
256 | # Business Intelligence projects
257 | *.rdl.data
258 | *.bim.layout
259 | *.bim_*.settings
260 | *.rptproj.rsuser
261 |
262 | # Microsoft Fakes
263 | FakesAssemblies/
264 |
265 | # GhostDoc plugin setting file
266 | *.GhostDoc.xml
267 |
268 | # Node.js Tools for Visual Studio
269 | .ntvs_analysis.dat
270 | node_modules/
271 |
272 | # Visual Studio 6 build log
273 | *.plg
274 |
275 | # Visual Studio 6 workspace options file
276 | *.opt
277 |
278 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
279 | *.vbw
280 |
281 | # Visual Studio LightSwitch build output
282 | **/*.HTMLClient/GeneratedArtifacts
283 | **/*.DesktopClient/GeneratedArtifacts
284 | **/*.DesktopClient/ModelManifest.xml
285 | **/*.Server/GeneratedArtifacts
286 | **/*.Server/ModelManifest.xml
287 | _Pvt_Extensions
288 |
289 | # Paket dependency manager
290 | .paket/paket.exe
291 | paket-files/
292 |
293 | # FAKE - F# Make
294 | .fake/
295 |
296 | # JetBrains Rider
297 | .idea/
298 | *.sln.iml
299 |
300 | # CodeRush
301 | .cr/
302 |
303 | # Python Tools for Visual Studio (PTVS)
304 | __pycache__/
305 | *.pyc
306 |
307 | # Cake - Uncomment if you are using it
308 | # tools/**
309 | # !tools/packages.config
310 |
311 | # Tabs Studio
312 | *.tss
313 |
314 | # Telerik's JustMock configuration file
315 | *.jmconfig
316 |
317 | # BizTalk build output
318 | *.btp.cs
319 | *.btm.cs
320 | *.odx.cs
321 | *.xsd.cs
322 |
323 | # OpenCover UI analysis results
324 | OpenCover/
325 |
326 | # Azure Stream Analytics local run output
327 | ASALocalRun/
328 |
329 | # MSBuild Binary and Structured Log
330 | *.binlog
331 |
332 | # NVidia Nsight GPU debugger configuration file
333 | *.nvuser
334 |
335 | # MFractors (Xamarin productivity tool) working folder
336 | .mfractor/
337 |
338 | # Local History for Visual Studio
339 | .localhistory/
340 |
341 |
342 | # End of https://www.gitignore.io/api/csharp
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
352 | # IDEs
353 | .idea/
354 | .vscode/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Deciding on Which Technology to Use
2 | While infrastructure as code (IaC) has existed within the AWS ecosystem since 2011, adoption has exploded recently due to the ability to manage large amounts of infrastructure at scale and standardize design across an organization. There are almost too many options between CloudFormation (CFN), CDK, and Terraform for IaC and Serverless Application Model (SAM) and Serverless Framework for development. [This article](https://acloudguru.com/blog/engineering/cloudformation-terraform-or-cdk-guide-to-iac-on-aws) from A Cloud Guru quickly sums up the pros and cons of each option. I choose this particular stack for some key reasons:
3 | - CDK allows the infrastructure and the CI/CD pipeline to be described as C# instead of YAML, JSON, or [HCL](https://www.terraform.io/docs/language/syntax/configuration.html)
4 | - CDK provides the ability to inject more robust logic than intrinsic functions in CloudFormation and more modularity as well while still being a native AWS offering
5 | - Docker ensures that the Lambda functions run consistently across local development, builds, and production environments and simplifies dependency management
6 | - [CDK Pipelines](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_pipelines.CdkPipeline.html) offer a higher level construct with much less configuration than CodePipeline and streamline management of multiple environments
7 |
8 | ## GitHub Repository
9 | You can find a complete working example [here](https://github.com/scottenriquez/dotnet-5-lambda-api-cdk).
10 |
11 | ## Initializing the Project
12 | Ensure that .NET 5 and the latest version of CDK are installed. To create a solution skeleton, run these commands in the root directory:
13 |
14 | ```shell
15 | # note that CDK uses this directory name as the solution name
16 | mkdir LambdaApiSolution
17 | cd LambdaApiSolution
18 | cdk init app --language=csharp
19 | # creates a CFN stack called CDKToolkit with an S3 bucket for staging purposes and configures IAM permissions for CI/CD
20 | cdk bootstrap --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess
21 | cdk deploy
22 | ```
23 |
24 | In order to use CDK Pipelines later on, a specific flag needs to be added to `cdk.json`:
25 | ```json
26 | {
27 | "app": "dotnet run -p src/LambdaApiSolution/LambdaApiSolution.csproj",
28 | "context": {
29 | ..
30 | "@aws-cdk/core:newStyleStackSynthesis": "true",
31 | ..
32 | }
33 | }
34 | ```
35 |
36 | At the time of writing, the generated CDK template uses .NET Core 3.1. Inside of the `.csproj` file, change the `TargetFramework` tag to `net5.0`.
37 |
38 | ```xml
39 |
40 |
41 | Exe
42 | net5.0
43 |
44 |
45 | ```
46 |
47 | From the `/LambdaApiSolution` directory, run these commands to create the serverless skeleton:
48 |
49 | ```shell
50 | # install the latest version of the .NET Lambda templates
51 | dotnet new -i Amazon.Lambda.Templates
52 | cd src/
53 | # create the function
54 | dotnet new lambda.image.EmptyFunction --name LambdaApiSolution.DockerFunction
55 | # add the projects to the solution file
56 | dotnet sln add LambdaApiSolution.DockerFunction/src/LambdaApiSolution.DockerFunction/LambdaApiSolution.DockerFunction.csproj
57 | dotnet sln add LambdaApiSolution.DockerFunction/test/LambdaApiSolution.DockerFunction.Tests/LambdaApiSolution.DockerFunction.Tests.csproj
58 | # build the solution and run the sample unit test to verify that everything is wired up correctly
59 | dotnet test LambdaApiSolution.sln
60 | ```
61 |
62 | ## Creating the Lambda Infrastructure and Build
63 | First, add the Lambda CDK NuGet package to the CDK project.
64 |
65 | ```xml
66 |
67 | ```
68 |
69 | Then, create the Docker image and Lambda function using CDK constructs in `LambdaApiSolutionStack.cs`:
70 |
71 | ```csharp
72 | public class LambdaApiSolutionStack : Stack
73 | {
74 | internal LambdaApiSolutionStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
75 | {
76 | // this path is relative to the directory where CDK commands are run
77 | // the directory must contain a Dockerfile
78 | DockerImageCode dockerImageCode = DockerImageCode.FromImageAsset("src/LambdaApiSolution.DockerFunction/src/LambdaApiSolution.DockerFunction");
79 | DockerImageFunction dockerImageFunction = new DockerImageFunction(this, "LambdaFunction", new DockerImageFunctionProps()
80 | {
81 | Code = dockerImageCode,
82 | Description = ".NET 5 Docker Lambda function"
83 | });
84 | }
85 | }
86 | ```
87 |
88 | Lastly, update the `Dockerfile` in the Lambda function project like so to build the C# code:
89 |
90 | ```dockerfile
91 | FROM public.ecr.aws/lambda/dotnet:5.0
92 | FROM mcr.microsoft.com/dotnet/sdk:5.0 as build-image
93 |
94 | ARG FUNCTION_DIR="/build"
95 | ARG CONFIGURATION="release"
96 | ENV PATH="/root/.dotnet/tools:${PATH}"
97 |
98 | RUN apt-get update && apt-get -y install zip
99 |
100 | RUN mkdir $FUNCTION_DIR
101 | WORKDIR $FUNCTION_DIR
102 | COPY Function.cs LambdaApiSolution.DockerFunction.csproj aws-lambda-tools-defaults.json $FUNCTION_DIR/
103 | RUN dotnet tool install -g Amazon.Lambda.Tools
104 |
105 | RUN mkdir -p build_artifacts
106 | RUN if [ "$CONFIGURATION" = "debug" ]; then dotnet lambda package --configuration Debug --package-type zip; else dotnet lambda package --configuration Release --package-type zip; fi
107 | RUN if [ "$CONFIGURATION" = "debug" ]; then cp -r /build/bin/Debug/net5.0/publish/* /build/build_artifacts; else cp -r /build/bin/Release/net5.0/publish/* /build/build_artifacts; fi
108 |
109 | FROM public.ecr.aws/lambda/dotnet:5.0
110 |
111 | COPY --from=build-image /build/build_artifacts/ /var/task/
112 | CMD ["LambdaApiSolution.DockerFunction::LambdaApiSolution.DockerFunction.Function::FunctionHandler"]
113 | ```
114 |
115 | At this point, you can now deploy the changes with the `cdk deploy` command. The Lambda function can be tested via the AWS Console. The easiest way to do so is to navigate to the CloudFormation stack, click on the function resource, and then create a test event with the string `"hello"` as the input. Note that this should not be a JSON object because the event handler's parameter currently accepts a single string.
116 |
117 | ## Integrating API Gateway
118 | Add the following packages to the CDK project:
119 |
120 | ```xml
121 |
122 |
123 | ```
124 |
125 | Next, you can add the API Gateway resources to the stack immediately after the `DockerImageFunction` in `LambdaApiSolutionStack.cs`:
126 |
127 | ```csharp
128 | HttpApi httpApi = new HttpApi(this, "APIGatewayForLambda", new HttpApiProps()
129 | {
130 | ApiName = "APIGatewayForLambda",
131 | CreateDefaultStage = true,
132 | CorsPreflight = new CorsPreflightOptions()
133 | {
134 | AllowMethods = new [] { HttpMethod.GET },
135 | AllowOrigins = new [] { "*" },
136 | MaxAge = Duration.Days(10)
137 | }
138 | });
139 | ```
140 | Then, create a Lambda proxy integration and a route for the function:
141 |
142 | ```csharp
143 | LambdaProxyIntegration lambdaProxyIntegration = new LambdaProxyIntegration(new LambdaProxyIntegrationProps()
144 | {
145 | Handler = dockerImageFunction,
146 | PayloadFormatVersion = PayloadFormatVersion.VERSION_2_0
147 | });
148 | httpApi.AddRoutes(new AddRoutesOptions()
149 | {
150 | Path = "/casing",
151 | Integration = lambdaProxyIntegration,
152 | Methods = new [] { HttpMethod.POST }
153 | });
154 | ```
155 |
156 | I used `/casing` for the path since the sample Lambda function returns an upper and lower case version of the input string. Finally, it's helpful to display the endpoint URL using a CFN output for testing.
157 |
158 | ```csharp
159 | // adding entropy to prevent a name collision
160 | string guid = Guid.NewGuid().ToString();
161 | CfnOutput apiUrl = new CfnOutput(this, "APIGatewayURLOutput", new CfnOutputProps()
162 | {
163 | ExportName = $"APIGatewayEndpointURL-{guid}",
164 | Value = httpApi.ApiEndpoint
165 | });
166 | ```
167 |
168 | With these changes to the resources, the Lambda function can be invoked by a `POST` request. The handler method parameters in `Function.cs` need to be updated for the request body to be passed in.
169 |
170 | ```csharp
171 | // replace the string parameter with a proxy request parameter
172 | public Casing FunctionHandler(APIGatewayProxyRequest apiGatewayProxyRequest, ILambdaContext context)
173 | {
174 | // update the input to use the proxy
175 | string input = apiGatewayProxyRequest.Body;
176 | return new Casing(input.ToLower(), input.ToUpper());
177 | }
178 | ```
179 |
180 | After successfully deploying the changes, the function can be tested in two ways. The first way is through an HTTP client like Postman. Add a string to the body parameter of the `POST` request. This action tests the full integration with API Gateway as well as the Lambda function. To test via the Lambda Console, update the test event from before to match the `APIGatewayProxyRequest` parameter:
181 |
182 | ```json
183 | {
184 | "body": "hello"
185 | }
186 | ```
187 |
188 | ## Adding CI/CD Using CDK Pipelines
189 | For this example, the source code resides in GitHub as opposed to CodeCommit. To grant the CI/CD pipeline access to the repository, a personal access token with `repo` permissions must be created via GitHub and stored in Secrets Manager as a plaintext format object. Note that for this codebase, I've named my secret `GitHub-Token`.
190 |
191 | Next, add the following packages to the CDK project:
192 | ```xml
193 |
194 |
195 |
196 |
197 |
198 | ```
199 |
200 | With these dependencies loaded, create a class called `PipelineStack.cs`. The following code creates a self-mutating CDK Pipeline, adds a GitHub source action to fetch the code using the token from Secrets Manager, and synthesizes the solution's CDK:
201 |
202 | ```csharp
203 | using Amazon.CDK;
204 | using Amazon.CDK.AWS.CodeBuild;
205 | using Amazon.CDK.AWS.CodePipeline;
206 | using Amazon.CDK.AWS.CodePipeline.Actions;
207 | using Amazon.CDK.Pipelines;
208 |
209 | namespace LambdaApiSolution
210 | {
211 | public class PipelineStack : Stack
212 | {
213 | internal PipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
214 | {
215 | Artifact_ sourceArtifact = new Artifact_();
216 | Artifact_ cloudAssemblyArtifact = new Artifact_();
217 | CdkPipeline pipeline = new CdkPipeline(this, "LambdaApiSolutionPipeline", new CdkPipelineProps()
218 | {
219 | CloudAssemblyArtifact = cloudAssemblyArtifact,
220 | PipelineName = "LambdaApiSolutionPipeline",
221 | SourceAction = new GitHubSourceAction(new GitHubSourceActionProps()
222 | {
223 | ActionName = "GitHubSource",
224 | Output = sourceArtifact,
225 | OauthToken = SecretValue.SecretsManager(Constants.GitHubTokenSecretsManagerId),
226 | Owner = Constants.Owner,
227 | Repo = Constants.RepositoryName,
228 | Branch = Constants.Branch,
229 | Trigger = GitHubTrigger.POLL
230 | }),
231 | SynthAction = new SimpleSynthAction(new SimpleSynthActionProps()
232 | {
233 | Environment = new BuildEnvironment
234 | {
235 | // required for .NET 5
236 | // https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
237 | BuildImage = LinuxBuildImage.STANDARD_5_0
238 | },
239 | SourceArtifact = sourceArtifact,
240 | CloudAssemblyArtifact = cloudAssemblyArtifact,
241 | Subdirectory = "LambdaApiSolution",
242 | InstallCommands = new[] {"npm install -g aws-cdk"},
243 | BuildCommands = new[] {"dotnet build src/LambdaApiSolution.sln"},
244 | SynthCommand = "cdk synth"
245 | })
246 | });
247 | }
248 | }
249 | }
250 |
251 | ```
252 |
253 | Remove the following line from `Program.cs` since the pipeline will deploy the API from now on:
254 | ```csharp
255 | new LambdaApiSolutionStack(app, "LambdaApiSolutionStack");
256 | ```
257 |
258 | Delete the previous stack, commit the latest changes to the source code so that they'll be available when the pipeline fetches the repo, and finally deploy the pipeline:
259 |
260 | ```shell
261 | cdk destroy
262 | git add .
263 | git commit -m "Adding source code to GitHub repository"
264 | git push origin main
265 | cdk deploy LambdaApiSolutionPipelineStack
266 | ```
267 |
268 | ## Creating Multiple Environments
269 | From now on, the pipeline will manage changes instead of manual `cdk deploy` commands. By merely pushing changes to the `main` branch, the pipeline will update itself and the other resources. The last feature in this example is adding development, test, and production environments. Rather than creating more stacks, we can leverage stages instead. Each environment will have a stage that makes a separate stack plus actions like approvals or integration testing. First, a stage must be defined in code. For this example, a stage will only contain an API stack.
270 |
271 | ```csharp
272 | using Amazon.CDK;
273 | using Construct = Constructs.Construct;
274 |
275 | namespace LambdaApiSolution
276 | {
277 | public class SolutionStage : Stage
278 | {
279 | public SolutionStage(Construct scope, string id, IStageProps props = null) : base(scope, id, props)
280 | {
281 | LambdaApiSolutionStack lambdaApiSolutionStack = new LambdaApiSolutionStack(this, "Solution");
282 | }
283 | }
284 | }
285 | ```
286 |
287 | To implement the stages, navigate back to `PipelineStack.cs` and append the following code after the pipeline declaration:
288 |
289 | ```csharp
290 | CdkStage developmentStage = pipeline.AddApplicationStage(new SolutionStage(this, "Development"));
291 | CdkStage testStage = pipeline.AddApplicationStage(new SolutionStage(this, "Test"));
292 | testStage.AddManualApprovalAction(new AddManualApprovalOptions()
293 | {
294 | ActionName = "PromoteToProduction"
295 | });
296 | CdkStage productionStage = pipeline.AddApplicationStage(new SolutionStage(this, "Production"));
297 | ```
298 |
299 | ## Next Steps
300 | The Lambda function, API Gateway, and multi-environment CI/CD pipeline are now in place. More Lambda functions can be added as separate C# projects. More stacks can be created and added to `SolutionStage.cs`.
--------------------------------------------------------------------------------
/LambdaApiSolution/src/.editorconfig:
--------------------------------------------------------------------------------
1 | ##########################################
2 | # Common Settings
3 | ##########################################
4 |
5 | # This file is the top-most EditorConfig file
6 | root = true
7 |
8 | # All Files
9 | [*]
10 | charset = utf-8
11 | indent_style = tab
12 | indent_size = 3
13 | insert_final_newline = true
14 | trim_trailing_whitespace = true
15 |
16 | ##########################################
17 | # File Extension Settings
18 | ##########################################
19 |
20 | # Visual Studio Solution Files
21 | [*.sln]
22 | indent_style = tab
23 |
24 | # Visual Studio XML Project Files
25 | [*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}]
26 | indent_size = 2
27 |
28 | # XML Configuration Files
29 | [*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}]
30 | indent_size = 2
31 |
32 | # JSON Files
33 | [*.{json,json5,webmanifest}]
34 | indent_size = 2
35 |
36 | # YAML Files
37 | [*.{yml,yaml}]
38 | indent_size = 2
39 |
40 | # Markdown Files
41 | [*.md]
42 | trim_trailing_whitespace = false
43 |
44 | # Web Files
45 | [*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,svg,vue}]
46 | indent_size = 2
47 |
48 | # Batch Files
49 | [*.{cmd,bat}]
50 | end_of_line = crlf
51 |
52 | # Bash Files
53 | [*.sh]
54 | end_of_line = lf
55 |
56 | # Makefiles
57 | [Makefile]
58 | indent_style = tab
59 |
60 | ##########################################
61 | # Default .NET Code Style Severities
62 | # https://docs.microsoft.com/dotnet/fundamentals/code-analysis/configuration-options#scope
63 | ##########################################
64 |
65 | [*.{cs,csx,cake,vb,vbx}]
66 | # Default Severity for all .NET Code Style rules below
67 | dotnet_analyzer_diagnostic.severity = warning
68 |
69 | ##########################################
70 | # File Header (Uncomment to support file headers)
71 | # https://docs.microsoft.com/visualstudio/ide/reference/add-file-header
72 | ##########################################
73 |
74 | # [*.{cs,csx,cake,vb,vbx}]
75 | # file_header_template = \n© PROJECT-AUTHOR\n
76 |
77 | # SA1636: File header copyright text should match
78 | # Justification: .editorconfig supports file headers. If this is changed to a value other than "none", a stylecop.json file will need to added to the project.
79 | # dotnet_diagnostic.SA1636.severity = none
80 |
81 | ##########################################
82 | # .NET Language Conventions
83 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions
84 | ##########################################
85 |
86 | # .NET Code Style Settings
87 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#net-code-style-settings
88 | [*.{cs,csx,cake,vb,vbx}]
89 | # "this." and "Me." qualifiers
90 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#this-and-me
91 | dotnet_style_qualification_for_field = true:warning
92 | dotnet_style_qualification_for_property = true:warning
93 | dotnet_style_qualification_for_method = true:warning
94 | dotnet_style_qualification_for_event = true:warning
95 | # Language keywords instead of framework type names for type references
96 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#language-keywords
97 | dotnet_style_predefined_type_for_locals_parameters_members = true:warning
98 | dotnet_style_predefined_type_for_member_access = true:warning
99 | # Modifier preferences
100 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#normalize-modifiers
101 | dotnet_style_require_accessibility_modifiers = always:warning
102 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning
103 | visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:warning
104 | dotnet_style_readonly_field = true:warning
105 | # Parentheses preferences
106 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parentheses-preferences
107 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
108 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
109 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
110 | dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion
111 | # Expression-level preferences
112 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
113 | dotnet_style_object_initializer = true:warning
114 | dotnet_style_collection_initializer = true:warning
115 | dotnet_style_explicit_tuple_names = true:warning
116 | dotnet_style_prefer_inferred_tuple_names = true:warning
117 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
118 | dotnet_style_prefer_auto_properties = true:warning
119 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
120 | dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion
121 | dotnet_diagnostic.IDE0045.severity = suggestion
122 | dotnet_style_prefer_conditional_expression_over_return = false:suggestion
123 | dotnet_diagnostic.IDE0046.severity = suggestion
124 | dotnet_style_prefer_compound_assignment = true:warning
125 | # Null-checking preferences
126 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#null-checking-preferences
127 | dotnet_style_coalesce_expression = true:warning
128 | dotnet_style_null_propagation = true:warning
129 | # Parameter preferences
130 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parameter-preferences
131 | dotnet_code_quality_unused_parameters = all:warning
132 | # More style options (Undocumented)
133 | # https://github.com/MicrosoftDocs/visualstudio-docs/issues/3641
134 | dotnet_style_operator_placement_when_wrapping = end_of_line
135 | # https://github.com/dotnet/roslyn/pull/40070
136 | dotnet_style_prefer_simplified_interpolation = true:warning
137 |
138 | # C# Code Style Settings
139 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-code-style-settings
140 | [*.{cs,csx,cake}]
141 | # Expression-bodied members
142 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-bodied-members
143 | csharp_style_expression_bodied_methods = true:warning
144 | csharp_style_expression_bodied_constructors = true:warning
145 | csharp_style_expression_bodied_operators = true:warning
146 | csharp_style_expression_bodied_properties = true:warning
147 | csharp_style_expression_bodied_indexers = true:warning
148 | csharp_style_expression_bodied_accessors = true:warning
149 | csharp_style_expression_bodied_lambdas = true:warning
150 | csharp_style_expression_bodied_local_functions = true:warning
151 | # Pattern matching
152 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#pattern-matching
153 | csharp_style_pattern_matching_over_is_with_cast_check = true:warning
154 | csharp_style_pattern_matching_over_as_with_null_check = true:warning
155 | # Inlined variable declarations
156 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#inlined-variable-declarations
157 | csharp_style_inlined_variable_declaration = true:warning
158 | # Expression-level preferences
159 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences
160 | csharp_prefer_simple_default_expression = true:warning
161 | # "Null" checking preferences
162 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-null-checking-preferences
163 | csharp_style_throw_expression = true:warning
164 | csharp_style_conditional_delegate_call = true:warning
165 | # Code block preferences
166 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#code-block-preferences
167 | csharp_prefer_braces = true:warning
168 | # Unused value preferences
169 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#unused-value-preferences
170 | csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
171 | dotnet_diagnostic.IDE0058.severity = suggestion
172 | csharp_style_unused_value_assignment_preference = discard_variable:suggestion
173 | dotnet_diagnostic.IDE0059.severity = suggestion
174 | # Index and range preferences
175 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#index-and-range-preferences
176 | csharp_style_prefer_index_operator = true:warning
177 | csharp_style_prefer_range_operator = true:warning
178 | # Miscellaneous preferences
179 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#miscellaneous-preferences
180 | csharp_style_deconstructed_variable_declaration = true:warning
181 | csharp_style_pattern_local_over_anonymous_function = true:warning
182 | csharp_using_directive_placement = inside_namespace:warning
183 | csharp_prefer_static_local_function = true:warning
184 | csharp_prefer_simple_using_statement = true:suggestion
185 | dotnet_diagnostic.IDE0063.severity = suggestion
186 |
187 | ##########################################
188 | # .NET Formatting Conventions
189 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference#formatting-conventions
190 | ##########################################
191 |
192 | # Organize usings
193 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#organize-using-directives
194 | dotnet_sort_system_directives_first = true
195 | # Newline options
196 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options
197 | csharp_new_line_before_open_brace = all
198 | csharp_new_line_before_else = true
199 | csharp_new_line_before_catch = true
200 | csharp_new_line_before_finally = true
201 | csharp_new_line_before_members_in_object_initializers = true
202 | csharp_new_line_before_members_in_anonymous_types = true
203 | csharp_new_line_between_query_expression_clauses = true
204 | # Indentation options
205 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#indentation-options
206 | csharp_indent_case_contents = true
207 | csharp_indent_switch_labels = true
208 | csharp_indent_labels = no_change
209 | csharp_indent_block_contents = true
210 | csharp_indent_braces = false
211 | csharp_indent_case_contents_when_block = false
212 | # Spacing options
213 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#spacing-options
214 | csharp_space_after_cast = false
215 | csharp_space_after_keywords_in_control_flow_statements = true
216 | csharp_space_between_parentheses = false
217 | csharp_space_before_colon_in_inheritance_clause = true
218 | csharp_space_after_colon_in_inheritance_clause = true
219 | csharp_space_around_binary_operators = before_and_after
220 | csharp_space_between_method_declaration_parameter_list_parentheses = false
221 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
222 | csharp_space_between_method_declaration_name_and_open_parenthesis = false
223 | csharp_space_between_method_call_parameter_list_parentheses = false
224 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
225 | csharp_space_between_method_call_name_and_opening_parenthesis = false
226 | csharp_space_after_comma = true
227 | csharp_space_before_comma = false
228 | csharp_space_after_dot = false
229 | csharp_space_before_dot = false
230 | csharp_space_after_semicolon_in_for_statement = true
231 | csharp_space_before_semicolon_in_for_statement = false
232 | csharp_space_around_declaration_statements = false
233 | csharp_space_before_open_square_brackets = false
234 | csharp_space_between_empty_square_brackets = false
235 | csharp_space_between_square_brackets = false
236 | # Wrapping options
237 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options
238 | csharp_preserve_single_line_statements = false
239 | csharp_preserve_single_line_blocks = true
240 |
241 | ##########################################
242 | # .NET Naming Conventions
243 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-naming-conventions
244 | ##########################################
245 |
246 | [*.{cs,csx,cake,vb,vbx}]
247 |
248 | ##########################################
249 | # Styles
250 | ##########################################
251 |
252 | # camel_case_style - Define the camelCase style
253 | dotnet_naming_style.camel_case_style.capitalization = camel_case
254 | # pascal_case_style - Define the PascalCase style
255 | dotnet_naming_style.pascal_case_style.capitalization = pascal_case
256 | # first_upper_style - The first character must start with an upper-case character
257 | dotnet_naming_style.first_upper_style.capitalization = first_word_upper
258 | # prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I'
259 | dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case
260 | dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I
261 | # prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T'
262 | dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case
263 | dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T
264 | # disallowed_style - Anything that has this style applied is marked as disallowed
265 | dotnet_naming_style.disallowed_style.capitalization = pascal_case
266 | dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____
267 | dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____
268 | # internal_error_style - This style should never occur... if it does, it indicates a bug in file or in the parser using the file
269 | dotnet_naming_style.internal_error_style.capitalization = pascal_case
270 | dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____
271 | dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____
272 |
273 | ##########################################
274 | # .NET Design Guideline Field Naming Rules
275 | # Naming rules for fields follow the .NET Framework design guidelines
276 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/index
277 | ##########################################
278 |
279 | # All public/protected/protected_internal constant fields must be PascalCase
280 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/field
281 | dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal
282 | dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const
283 | dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field
284 | dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group
285 | dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = pascal_case_style
286 | dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning
287 |
288 | # All public/protected/protected_internal static readonly fields must be PascalCase
289 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/field
290 | dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal
291 | dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly
292 | dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field
293 | dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group
294 | dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style
295 | dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning
296 |
297 | # No other public/protected/protected_internal fields are allowed
298 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/field
299 | dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal
300 | dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field
301 | dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group
302 | dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style
303 | dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error
304 |
305 | ##########################################
306 | # StyleCop Field Naming Rules
307 | # Naming rules for fields follow the StyleCop analyzers
308 | # This does not override any rules using disallowed_style above
309 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers
310 | ##########################################
311 |
312 | # All constant fields must be PascalCase
313 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md
314 | dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
315 | dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const
316 | dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field
317 | dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group
318 | dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = pascal_case_style
319 | dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning
320 |
321 | # All static readonly fields must be PascalCase
322 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md
323 | dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
324 | dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly
325 | dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field
326 | dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group
327 | dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style
328 | dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning
329 |
330 | # No non-private instance fields are allowed
331 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md
332 | dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
333 | dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field
334 | dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group
335 | dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style
336 | dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error
337 |
338 | # Private fields must be camelCase
339 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md
340 | dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities = private
341 | dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds = field
342 | dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group
343 | dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style = camel_case_style
344 | dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity = warning
345 |
346 | # Local variables must be camelCase
347 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
348 | dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local
349 | dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local
350 | dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group
351 | dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style
352 | dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = silent
353 |
354 | # This rule should never fire. However, it's included for at least two purposes:
355 | # First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers.
356 | # Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#).
357 | dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities = *
358 | dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds = field
359 | dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_check_uncovered_field_case_group
360 | dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style
361 | dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error
362 |
363 |
364 | ##########################################
365 | # Other Naming Rules
366 | ##########################################
367 |
368 | # All of the following must be PascalCase:
369 | # - Namespaces
370 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces
371 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
372 | # - Classes and Enumerations
373 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
374 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
375 | # - Delegates
376 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types
377 | # - Constructors, Properties, Events, Methods
378 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members
379 | dotnet_naming_symbols.element_group.applicable_kinds = namespace, class, enum, struct, delegate, event, method, property
380 | dotnet_naming_rule.element_rule.symbols = element_group
381 | dotnet_naming_rule.element_rule.style = pascal_case_style
382 | dotnet_naming_rule.element_rule.severity = warning
383 |
384 | # Interfaces use PascalCase and are prefixed with uppercase 'I'
385 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
386 | dotnet_naming_symbols.interface_group.applicable_kinds = interface
387 | dotnet_naming_rule.interface_rule.symbols = interface_group
388 | dotnet_naming_rule.interface_rule.style = prefix_interface_with_i_style
389 | dotnet_naming_rule.interface_rule.severity = warning
390 |
391 | # Generics Type Parameters use PascalCase and are prefixed with uppercase 'T'
392 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
393 | dotnet_naming_symbols.type_parameter_group.applicable_kinds = type_parameter
394 | dotnet_naming_rule.type_parameter_rule.symbols = type_parameter_group
395 | dotnet_naming_rule.type_parameter_rule.style = prefix_type_parameters_with_t_style
396 | dotnet_naming_rule.type_parameter_rule.severity = warning
397 |
398 | # Function parameters use camelCase
399 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters
400 | dotnet_naming_symbols.parameters_group.applicable_kinds = parameter
401 | dotnet_naming_rule.parameters_rule.symbols = parameters_group
402 | dotnet_naming_rule.parameters_rule.style = camel_case_style
403 | dotnet_naming_rule.parameters_rule.severity = warning
--------------------------------------------------------------------------------