Disclaimer: I am a consultant at Amazon Web Services, and this is my personal blog. The opinions expressed here are solely mine and do not reflect the views of Amazon Web Services (AWS). Any statements made should not be considered official endorsements or statements by AWS.
In this post, we will understand how can we implement the following things when using AWS Lambda with .NET Core.
When we create an AWS Lambda project in Visual Studio, we just get the basic FunctionHandler
method inside Function
class.
.NET Core features such as Configuration, Logging & Dependency Injection are not enabled by default. We need to write some additional code to enable these features.
Although, Logging is enabled by default, that uses the lambda logger, not the .NET Core's default logger.
We will be implementing the following things in this post further.
appsettings.json
file & Environment Variables
.Console
logging.ServiceCollection
.We would need the below packages to implement Configuration, Logging & Dependency Injection in our Lambda project. Just update csproj
file to have ItemGroup
section like below, or install these packages manually.
<ItemGroup>
<!-- Default Lambda packages specific to Lambda -->
<PackageReference Include="Amazon.Lambda.Core" Version="2.1.0" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.3.0" />
<!-- Packages required for Dependency Injection -->
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="AWSSDK.Extensions.NETCore.Setup" Version="3.7.2" />
<PackageReference Include="AWSSDK.S3" Version="3.7.9.2" />
<!-- Packages required for Configuration -->
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<!---->
<!-- Packages required for Logging -->
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
</ItemGroup>
Startup
class fileCreate a Startup.cs
class file with the below content. Code is self-explanatory.
public class Startup
{
private readonly IConfigurationRoot Configuration;
public Startup()
{
Configuration = new ConfigurationBuilder() // ConfigurationBuilder() method requires Microsoft.Extensions.Configuration NuGet package
.SetBasePath(Directory.GetCurrentDirectory()) // SetBasePath() method requires Microsoft.Extensions.Configuration.FileExtensions NuGet package
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) // AddJsonFile() method requires Microsoft.Extensions.Configuration.Json NuGet package
.AddEnvironmentVariables() // AddEnvironmentVariables() method requires Microsoft.Extensions.Configuration.EnvironmentVariables NuGet package
.Build();
}
public IServiceProvider ConfigureServices()
{
var services = new ServiceCollection(); // ServiceCollection require Microsoft.Extensions.DependencyInjection NuGet package
ConfigureLoggingAndConfigurations(services);
ConfigureApplicationServices(services);
IServiceProvider provider = services.BuildServiceProvider();
return provider;
}
private void ConfigureLoggingAndConfigurations(ServiceCollection services)
{
// Add configuration service
services.AddSingleton<IConfiguration>(Configuration);
// Add logging service
services.AddLogging(loggingBuilder => // AddLogging() requires Microsoft.Extensions.Logging NuGet package
{
loggingBuilder.ClearProviders();
loggingBuilder.AddConsole(); // AddConsole() requires Microsoft.Extensions.Logging.Console NuGet package
});
}
private void ConfigureApplicationServices(ServiceCollection services)
{
#region AWS SDK setup
// Get the AWS profile information from configuration providers
AWSOptions awsOptions = Configuration.GetAWSOptions();
// Configure AWS service clients to use these credentials
services.AddDefaultAWSOptions(awsOptions);
// These AWS service clients will be singleton by default
services.AddAWSService<IAmazonS3>();
#endregion
services.AddSingleton<ILambdaEntryPoint, LambdaEntryPoint>();
}
}
You may also need to add the below namespaces.
using Amazon.Extensions.NETCore.Setup;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
LambdaEntryPoint
classCreate LambdaEntryPoint
class with Handler
method. Inject all the dependencies inside the constructor of this class. We will invoke Handler
method of this class from the original FunctionHandler
.
ILambdaEntryPoint
interfacepublic interface ILambdaEntryPoint
{
Task<string> Handler(string input);
}
LambdaEntryPoint
classpublic class LambdaEntryPoint : ILambdaEntryPoint
{
private readonly ILogger<LambdaEntryPoint> _logger;
public LambdaEntryPoint(ILogger<LambdaEntryPoint> logger)
{
_logger = logger;
}
public async Task<string> Handler(string input)
{
_logger.LogInformation("Handler invoked");
return $"Hello {input}";
}
}
Function.cs
classNow replace Function
class content with the below content.
Here, we are mainly doing 2 things:
ConfigureServices()
method of Startup
class. This method will register all the services in ServiceCollection
and return an instance of IServiceProvider
.FunctionHandler
, we are calling _lambdaEntryPoint.Handler(input)
method to do the actual processing.Also, it is important to understand, Function
class is Singleton in AWS Lambda. Multiple invocations of AWS Lambda will not execute Constructor logic multiple times, which will be executed only once in the beginning, and the class will remain singleton until the Lambda compute is alive.
public class Function
{
private readonly ILambdaEntryPoint _lambdaEntryPoint;
public Function()
{
var startup = new Startup();
IServiceProvider provider = startup.ConfigureServices();
_lambdaEntryPoint = provider.GetRequiredService<ILambdaEntryPoint>();
}
public async Task<string> FunctionHandler(string input, ILambdaContext context)
{
return await _lambdaEntryPoint.Handler(input);
}
}
That's all.
In this post, we learned how easily we can set up configuration, logging and dependency injection in AWS Lambda when using with .NET Core. Please let me know your thoughts and feedback in the comment section below.
Thank You ❤️