Skip to content

Commit 144df7c

Browse files
Amazon Web ServicesPavel Safronov
Amazon Web Services
authored and
Pavel Safronov
committed
Initial commit of AWS Lambda packages.
0 parents  commit 144df7c

File tree

216 files changed

+13145
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

216 files changed

+13145
-0
lines changed

Diff for: .gitignore

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
######################################
2+
# Visual Studio per-user settings data
3+
######################################
4+
*.suo
5+
*.user
6+
7+
####################
8+
# Build/Test folders
9+
####################
10+
**/.vs/
11+
**/bin/
12+
**/obj/
13+
**/TestResults/
14+
**/Temp/
15+
**/NuGet.exe
16+
**/buildlogs/
17+
**/Deployment/
18+
**/packages
19+
**/launchSettings.json
20+
21+
**/project.lock.json
22+
23+
24+
**/node_modules/
25+
**/TestGenerations/
26+
/Blueprints/YeomanGenerator/generator-aws-lambda-dotnet/Blueprints/**
27+
/Blueprints/YeomanGenerator/generator-aws-lambda-dotnet/app/manifest.js
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"display-name":"Blog API using DynamoDB",
3+
"system-name":"DynamoDBBlogAPI",
4+
"description": "An AWS Serverless application example Blogging API using Amazon DynamoDB.",
5+
"sort-order" : 201,
6+
"hidden-tags" : ["C#","ServerlessProject"],
7+
"tags":["DynamoDB"]
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
6+
namespace BLUEPRINT_BASE_NAME
7+
{
8+
public class Blog
9+
{
10+
public string Id { get; set; }
11+
public string Name { get; set; }
12+
public string Content { get; set; }
13+
public DateTime CreatedTimestamp { get; set; }
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Net;
5+
using System.Threading.Tasks;
6+
7+
using Amazon.Lambda.Core;
8+
using Amazon.Lambda.APIGatewayEvents;
9+
10+
using Amazon;
11+
using Amazon.DynamoDBv2;
12+
using Amazon.DynamoDBv2.DataModel;
13+
14+
using Newtonsoft.Json;
15+
16+
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
17+
[assembly: LambdaSerializerAttribute(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
18+
19+
namespace BLUEPRINT_BASE_NAME
20+
{
21+
public class Functions
22+
{
23+
// This const is the name of the environment variable that the serverless.template will use to set
24+
// the name of the DynamoDB table used to store blog posts.
25+
const string TABLENAME_ENVIRONMENT_VARIABLE_LOOKUP = "BlogTable";
26+
27+
public const string ID_QUERY_STRING_NAME = "Id";
28+
IDynamoDBContext DDBContext { get; set; }
29+
30+
/// <summary>
31+
/// Default constructor that Lambda will invoke.
32+
/// </summary>
33+
public Functions()
34+
{
35+
// Check to see if a table name was passed in through environment variables and if so
36+
// add the table mapping.
37+
var tableName = System.Environment.GetEnvironmentVariable(TABLENAME_ENVIRONMENT_VARIABLE_LOOKUP);
38+
if(!string.IsNullOrEmpty(tableName))
39+
{
40+
AWSConfigsDynamoDB.Context.TypeMappings[typeof(Blog)] = new Amazon.Util.TypeMapping(typeof(Blog), tableName);
41+
}
42+
43+
var config = new DynamoDBContextConfig { Conversion = DynamoDBEntryConversion.V2 };
44+
this.DDBContext = new DynamoDBContext(new AmazonDynamoDBClient(), config);
45+
}
46+
47+
/// <summary>
48+
/// Constructor used for testing passing in a preconfigured DynamoDB client.
49+
/// </summary>
50+
/// <param name="ddbClient"></param>
51+
/// <param name="tableName"></param>
52+
public Functions(IAmazonDynamoDB ddbClient, string tableName)
53+
{
54+
if (!string.IsNullOrEmpty(tableName))
55+
{
56+
AWSConfigsDynamoDB.Context.TypeMappings[typeof(Blog)] = new Amazon.Util.TypeMapping(typeof(Blog), tableName);
57+
}
58+
59+
var config = new DynamoDBContextConfig { Conversion = DynamoDBEntryConversion.V2 };
60+
this.DDBContext = new DynamoDBContext(ddbClient, config);
61+
}
62+
63+
/// <summary>
64+
/// A Lambda function that returns back a page worth of blog posts.
65+
/// </summary>
66+
/// <param name="request"></param>
67+
/// <returns>The list of blogs</returns>
68+
public async Task<APIGatewayProxyResponse> GetBlogsAsync(APIGatewayProxyRequest request, ILambdaContext context)
69+
{
70+
context.Logger.LogLine("Getting blogs");
71+
var search = this.DDBContext.ScanAsync<Blog>(null);
72+
var page = await search.GetNextSetAsync();
73+
context.Logger.LogLine($"Found {page.Count} blogs");
74+
75+
var response = new APIGatewayProxyResponse
76+
{
77+
StatusCode = (int)HttpStatusCode.OK,
78+
Body = JsonConvert.SerializeObject(page),
79+
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
80+
};
81+
82+
return response;
83+
}
84+
85+
/// <summary>
86+
/// A Lambda function that returns the blog identified by blogId
87+
/// </summary>
88+
/// <param name="request"></param>
89+
/// <returns></returns>
90+
public async Task<APIGatewayProxyResponse> GetBlogAsync(APIGatewayProxyRequest request, ILambdaContext context)
91+
{
92+
var blogId = request?.PathParameters[ID_QUERY_STRING_NAME];
93+
if (string.IsNullOrEmpty(blogId))
94+
blogId = request?.QueryStringParameters[ID_QUERY_STRING_NAME];
95+
96+
if (string.IsNullOrEmpty(blogId))
97+
{
98+
return new APIGatewayProxyResponse
99+
{
100+
StatusCode = (int)HttpStatusCode.BadRequest,
101+
Body = "Missing required parameter blogId"
102+
};
103+
}
104+
105+
context.Logger.LogLine($"Getting blog {blogId}");
106+
var blog = await DDBContext.LoadAsync<Blog>(blogId);
107+
context.Logger.LogLine($"Found blog: {blog != null}");
108+
109+
if (blog == null)
110+
{
111+
return new APIGatewayProxyResponse
112+
{
113+
StatusCode = (int)HttpStatusCode.NotFound
114+
};
115+
}
116+
117+
var response = new APIGatewayProxyResponse
118+
{
119+
StatusCode = (int)HttpStatusCode.OK,
120+
Body = JsonConvert.SerializeObject(blog),
121+
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
122+
};
123+
return response;
124+
}
125+
126+
/// <summary>
127+
/// A Lambda function that adds a blog post.
128+
/// </summary>
129+
/// <param name="request"></param>
130+
/// <returns></returns>
131+
public async Task<APIGatewayProxyResponse> AddBlogAsync(APIGatewayProxyRequest request, ILambdaContext context)
132+
{
133+
var blog = JsonConvert.DeserializeObject<Blog>(request?.Body);
134+
blog.Id = Guid.NewGuid().ToString();
135+
blog.CreatedTimestamp = DateTime.Now;
136+
137+
context.Logger.LogLine($"Saving blog with id {blog.Id}");
138+
await DDBContext.SaveAsync<Blog>(blog);
139+
140+
var response = new APIGatewayProxyResponse
141+
{
142+
StatusCode = (int)HttpStatusCode.OK,
143+
Body = blog.Id.ToString(),
144+
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
145+
};
146+
return response;
147+
}
148+
149+
/// <summary>
150+
/// A Lambda function that removes a blog post from the DynamoDB table.
151+
/// </summary>
152+
/// <param name="request"></param>
153+
public async Task<APIGatewayProxyResponse> RemoveBlogAsync(APIGatewayProxyRequest request, ILambdaContext context)
154+
{
155+
var blogId = request?.PathParameters[ID_QUERY_STRING_NAME];
156+
if (string.IsNullOrEmpty(blogId))
157+
blogId = request?.QueryStringParameters[ID_QUERY_STRING_NAME];
158+
159+
if (string.IsNullOrEmpty(blogId))
160+
{
161+
return new APIGatewayProxyResponse
162+
{
163+
StatusCode = (int)HttpStatusCode.BadRequest,
164+
Body = "Missing required parameter blogId"
165+
};
166+
}
167+
168+
context.Logger.LogLine($"Deleting blog with id {blogId}");
169+
await this.DDBContext.DeleteAsync<Blog>(blogId);
170+
171+
return new APIGatewayProxyResponse
172+
{
173+
StatusCode = (int)HttpStatusCode.OK
174+
};
175+
}
176+
}
177+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Amazon DynamoDB Blog API Serverless Application Project
2+
3+
This starter project consists of:
4+
* serverless.template - an AWS CloudFormation Serverless Application Model template file for declaring your Serverless functions and other AWS resources
5+
* Function.cs - class file containing the C# methods mapped to the Serverless functions declared in the template file
6+
* Blog.cs - file containing a C# class representing a blog entry in the DynamoDB table
7+
* aws-lambda-tools-defaults.json - default argument settings for use with Visual Studio and command line deployment tools for AWS
8+
* project.json - .NET Core project file with build and tool declarations for the Amazon.Lambda.Tools Nuget package
9+
10+
You may also have a test project depending on the options selected.
11+
12+
The generated project contains a Serverless template declaration for a simple web API for blogging with the blog data stored in a DynamoDB table. The blogging API functions are hosted as a set of AWS Lambda functions that will be exposed through Amazon API Gateway as HTTP operations. Edit the template to customize the functions or add more functions and other resources needed by your application, and edit the function code in Function.cs/Blog.cs. You can then deploy your Serverless application.
13+
14+
## Here are some steps to follow from Visual Studio:
15+
16+
To deploy your Serverless application, right click the project in Solution Explorer and select *Publish to AWS Lambda*.
17+
18+
To view your deployed application open the Stack View window by double-clicking the stack name shown beneath the AWS CloudFormation node in the AWS Explorer tree. The Stack View also displays the root URL to your published application.
19+
20+
## Here are some steps to follow to get started from the command line:
21+
22+
Once you have edited your template and code you can use the following command lines to deploy your application from the command line (these examples assume the project name is *EmptyServerless*):
23+
24+
Restore dependencies
25+
```
26+
cd "EmptyServerless"
27+
dotnet restore
28+
```
29+
30+
Execute unit tests
31+
```
32+
cd "EmptyServerless/test/EmptyServerless.Tests"
33+
dotnet test
34+
```
35+
36+
Deploy application
37+
```
38+
cd "EmptyServerless/src/EmptyServerless"
39+
dotnet lambda deploy-serverless
40+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
6+
"dotnet lambda help",
7+
8+
"All the command line options for the Lambda command can be specified in this file."
9+
],
10+
11+
"profile": "",
12+
"region": "",
13+
"configuration": "Release",
14+
"framework": "netcoreapp1.0",
15+
"s3-prefix": "BLUEPRINT_BASE_NAME/",
16+
"template": "serverless.template",
17+
"template-parameters": ""
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"version": "1.0.0-*",
3+
"buildOptions": {
4+
"emitEntryPoint": false
5+
},
6+
7+
"dependencies": {
8+
"Microsoft.NETCore.App": {
9+
"type": "platform",
10+
"version": "1.0.1"
11+
},
12+
13+
"Newtonsoft.Json": "9.0.1",
14+
15+
"Amazon.Lambda.Core": "1.0.0",
16+
"Amazon.Lambda.APIGatewayEvents": "1.0.0",
17+
"Amazon.Lambda.Serialization.Json": "1.0.0",
18+
19+
"Amazon.Lambda.Tools": {
20+
"version": "1.0.0-preview1",
21+
"type": "build"
22+
},
23+
24+
"AWSSDK.DynamoDBv2": "3.3.1"
25+
},
26+
27+
"tools": {
28+
"Amazon.Lambda.Tools": "1.0.0-preview1"
29+
},
30+
31+
"frameworks": {
32+
"netcoreapp1.0": {
33+
"imports": "dnxcore50"
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)