CommandQuery.AWSLambda
3.0.0
There is a newer version of this package available.
See the version list below for details.
See the version list below for details.
dotnet add package CommandQuery.AWSLambda --version 3.0.0
NuGet\Install-Package CommandQuery.AWSLambda -Version 3.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CommandQuery.AWSLambda" Version="3.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add CommandQuery.AWSLambda --version 3.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: CommandQuery.AWSLambda, 3.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install CommandQuery.AWSLambda as a Cake Addin #addin nuget:?package=CommandQuery.AWSLambda&version=3.0.0 // Install CommandQuery.AWSLambda as a Cake Tool #tool nuget:?package=CommandQuery.AWSLambda&version=3.0.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
CommandQuery.AWSLambda ⚡
Command Query Separation for AWS Lambda
- Provides generic function support for commands and queries with Amazon API Gateway
- Enables APIs based on HTTP
POST
andGET
Get Started
- Install AWS Toolkit for Visual Studio
- Create a new AWS Serverless Application (.NET Core) project
- Install the
CommandQuery.AWSLambda
package from NuGetPM>
Install-Package CommandQuery.AWSLambda
- Create functions
- Preferably named
Command
andQuery
- Preferably named
- Create commands and command handlers
- Implement
ICommand
andICommandHandler<in TCommand>
- Or
ICommand<TResult>
andICommandHandler<in TCommand, TResult>
- Implement
- Create queries and query handlers
- Implement
IQuery<TResult>
andIQueryHandler<in TQuery, TResult>
- Implement
- Configure the serverless template
Choose:
- Empty Serverless Application
Commands
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using CommandQuery.AWSLambda;
using CommandQuery.Sample.Contracts.Commands;
using CommandQuery.Sample.Handlers;
using CommandQuery.Sample.Handlers.Commands;
using Microsoft.Extensions.DependencyInjection;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace CommandQuery.Sample.AWSLambda;
public class Command
{
private readonly ICommandFunction _commandFunction;
public Command()
{
var services = new ServiceCollection();
//services.AddSingleton(new JsonSerializerOptions(JsonSerializerDefaults.Web));
services.AddCommandFunction(typeof(FooCommandHandler).Assembly, typeof(FooCommand).Assembly);
// Add handler dependencies
services.AddTransient<ICultureService, CultureService>();
var serviceProvider = services.BuildServiceProvider();
serviceProvider.GetService<ICommandProcessor>().AssertConfigurationIsValid(); // Validation
_commandFunction = serviceProvider.GetService<ICommandFunction>();
}
public async Task<APIGatewayProxyResponse> Handle(APIGatewayProxyRequest request, ILambdaContext context) =>
await _commandFunction.HandleAsync(request.PathParameters["commandName"], request, context.Logger);
}
- The function is requested via HTTP
POST
with the Content-Typeapplication/json
in the header. - The name of the command is the slug of the URL.
- The command itself is provided as JSON in the body.
- If the command succeeds; the response is empty with the HTTP status code
200
. - If the command fails; the response is an error message with the HTTP status code
400
or500
.
Commands with result:
- If the command succeeds; the response is the result as JSON with the HTTP status code
200
.
Queries
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using CommandQuery.AWSLambda;
using CommandQuery.Sample.Contracts.Queries;
using CommandQuery.Sample.Handlers;
using CommandQuery.Sample.Handlers.Queries;
using Microsoft.Extensions.DependencyInjection;
namespace CommandQuery.Sample.AWSLambda
{
public class Query
{
private readonly IQueryFunction _queryFunction;
public Query()
{
var services = new ServiceCollection();
//services.AddSingleton(new JsonSerializerOptions(JsonSerializerDefaults.Web));
services.AddQueryFunction(typeof(BarQueryHandler).Assembly, typeof(BarQuery).Assembly);
// Add handler dependencies
services.AddTransient<IDateTimeProxy, DateTimeProxy>();
var serviceProvider = services.BuildServiceProvider();
serviceProvider.GetService<IQueryProcessor>().AssertConfigurationIsValid(); // Validation
_queryFunction = serviceProvider.GetService<IQueryFunction>();
}
public async Task<APIGatewayProxyResponse> Handle(APIGatewayProxyRequest request, ILambdaContext context) =>
await _queryFunction.HandleAsync(request.PathParameters["queryName"], request, context.Logger);
}
}
- The function is requested via:
- HTTP
POST
with the Content-Typeapplication/json
in the header and the query itself as JSON in the body - HTTP
GET
and the query itself as query string parameters in the URL
- HTTP
- The name of the query is the slug of the URL.
- If the query succeeds; the response is the result as JSON with the HTTP status code
200
. - If the query fails; the response is an error message with the HTTP status code
400
or500
.
Configuration
Configuration in serverless.template
:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Transform": "AWS::Serverless-2016-10-31",
"Description": "An AWS Serverless Application.",
"Resources": {
"Command": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Architectures": [
"x86_64"
],
"Handler": "CommandQuery.Sample.AWSLambda::CommandQuery.Sample.AWSLambda.Command::Handle",
"Runtime": "dotnet6",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambdaBasicExecutionRole"
],
"Events": {
"PostResource": {
"Type": "Api",
"Properties": {
"Path": "/command/{commandName}",
"Method": "POST"
}
}
}
}
},
"Query": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Architectures": [
"x86_64"
],
"Handler": "CommandQuery.Sample.AWSLambda::CommandQuery.Sample.AWSLambda.Query::Handle",
"Runtime": "dotnet6",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambdaBasicExecutionRole"
],
"Events": {
"GetResource": {
"Type": "Api",
"Properties": {
"Path": "/query/{queryName}",
"Method": "GET"
}
},
"PostResource": {
"Type": "Api",
"Properties": {
"Path": "/query/{queryName}",
"Method": "POST"
}
}
}
}
}
},
"Outputs": {
"ApiURL": {
"Description": "API endpoint URL for Prod environment",
"Value": {
"Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
}
}
}
}
Testing
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using Amazon.Lambda.TestUtilities;
using CommandQuery.Sample.Contracts.Queries;
using FluentAssertions;
using NUnit.Framework;
namespace CommandQuery.Sample.AWSLambda.Tests
{
public class QueryTests
{
public class when_using_the_real_function_via_Post
{
[SetUp]
public void SetUp()
{
Subject = new Query();
Request = GetRequest("POST", content: "{ \"Id\": 1 }");
Context = new TestLambdaContext();
}
[Test]
public async Task should_work()
{
var result = await Subject.Handle(Request.QueryName("BarQuery"), Context);
var value = result.As<Bar>();
value.Id.Should().Be(1);
value.Value.Should().NotBeEmpty();
}
[Test]
public async Task should_handle_errors()
{
var result = await Subject.Handle(Request.QueryName("FailQuery"), Context);
result.ShouldBeError("The query type 'FailQuery' could not be found");
}
Query Subject;
APIGatewayProxyRequest Request;
ILambdaContext Context;
}
public class when_using_the_real_function_via_Get
{
[SetUp]
public void SetUp()
{
Subject = new Query();
Request = GetRequest("GET", query: new Dictionary<string, IList<string>> { { "Id", new List<string> { "1" } } });
Context = new TestLambdaContext();
}
[Test]
public async Task should_work()
{
var result = await Subject.Handle(Request.QueryName("BarQuery"), Context);
var value = result.As<Bar>();
value.Id.Should().Be(1);
value.Value.Should().NotBeEmpty();
}
[Test]
public async Task should_handle_errors()
{
var result = await Subject.Handle(Request.QueryName("FailQuery"), Context);
result.ShouldBeError("The query type 'FailQuery' could not be found");
}
Query Subject;
APIGatewayProxyRequest Request;
ILambdaContext Context;
}
static APIGatewayProxyRequest GetRequest(string method, string content = null, Dictionary<string, IList<string>> query = null)
{
var request = new APIGatewayProxyRequest
{
HttpMethod = method,
Body = content,
MultiValueQueryStringParameters = query
};
return request;
}
}
}
Samples
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- Amazon.Lambda.APIGatewayEvents (>= 2.5.0)
- Amazon.Lambda.Core (>= 2.1.0)
- CommandQuery (>= 3.0.0)
- CommandQuery.SystemTextJson (>= 3.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on CommandQuery.AWSLambda:
Repository | Stars |
---|---|
hlaueriksson/CommandQuery
Command Query Separation for 🌐ASP.NET Core ⚡AWS Lambda ⚡Azure Functions ⚡Google Cloud Functions
|
- Change TargetFramework to netstandard2.0
- Bump Amazon.Lambda.Core to 2.1.0
- Bump Amazon.Lambda.APIGatewayEvents to 2.5.0