Using Serverless Framework Environment Variables .net core Lambda
Tags: csharp, aws, dotnet, serverless
Published: 2019-04-27 17:51:18

---
title: Using Serverless Framework Environment Variables .net core Lambda
published: true
tags: Csharp,AWS,dotnet,serverless
canonical_url: https://garywoodfine.com/using-serverless-framework-environment-variables-net-core-lambda/
---

In previous posts, have explored [getting started with Serverless Framework](https://garywoodfine.com/net-core-serverless-framework/) and [how to implement Simple Dependency Injection](https://dev.to/gary_woodfine/simple-dependency-injection-in-aws-lambda-5cgj-temp-slug-4239809) and then we explored how to implement more [advanced dependency injection concepts relating to AWS Lambda.](https://dev.to/gary_woodfine/serverless-aws-lambda-dependency-injection-5e15-temp-slug-8854152)

In each of these posts, we explored different levels of interactivity and how [the Serverless Framework helps you develop and deploy your AWS Lambda functions](https://serverless.com/framework/docs/providers/aws/guide/intro/) and .net core and C#. In this post, we are going to delve a little deeper again into one specific area of how you can create Environment Variables with the Serverless Framework and share them with the .net core executable.

This is a useful strategy to learn as it helps you to create easily configurable and maintainable infrastructure as code and helps to element those [Magic Strings](https://dev.to/gary_woodfine/book-review-java-by-comparison-2bnc-temp-slug-8485303) from your code base.

We are going to make use of the `serverless.yml` to create our environment variables so if you not all that familiar with it then I recommend reading the high-level [serverless.yml reference](https://serverless.com/framework/docs/providers/aws/guide/serverless.yml/) but I will explain the features we’re going to use as I go through.

### Environment Variables in Serverless Framework

The Environment tag in the Serverless Framework YAML file enables you to create service-wide environment variables which you can easily make use of in other programming languages, for instance in nodejs based lambda functions you could simply create an environment variable in your `serverless.yml` as follows

```js
Environment:
    Variables:
      TABLE_NAME: SomeTableName

```

You can then simply reference and get the value from the environment variable in your code as follows

```js
const tableName = process.env.TABLE_NAME;

```

This is because of one of the [many quirks of the JavaScript that make it both a pleasure and pain to work with in equal amounts](https://dev.to/gary_woodfine/book-review--javascript-the-good-parts-4pdf-temp-slug-8222188) and also because the [process object is a global that provides information about, and control over, the current Node.js process](https://nodejs.org/api/process.html#process_process)

In .net core however there is a little bit additional work required but, in my opinion at least, is worth it when it comes to managing variables etc.

We will be building on the code base I introduced in [how to implement Simple Dependency Injection](https://dev.to/gary_woodfine/simple-dependency-injection-in-aws-lambda-5cgj-temp-slug-4239809) the branch we’ll be using is `EnvironmentVariables`

{% github garywoodfine/HelloConfiguration %}

### How to use Environment Variables in .net core

In order to extend our AWS Lambda application to make use of Environment Variables we will need to add an additional reference to our application.

```bash
dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables –version 2.1.0

```

Once this is added we can now add an environment variable to our serverless.yml. We’ll create an environment variable called SaySomething and provide some arbitary statement.

```javascript

service: Hello-Configuration

provider:
  name: aws
  runtime: dotnetcore2.1
  environment:
    SaySomething: "Eating coconuts is cool"
  
package:
  individually: true

functions:
  hello:
    handler: HelloConfiguration::Threenine.ConfigTest.Functions.Speak::Greet


    package:
      artifact: bin/release/netcoreapp2.1/hello.zip


```

We can then edit our `LambdaConfiguration.cs` to the below

```csharp
using System.IO;
using Microsoft.Extensions.Configuration;

namespace Threenine.ConfigTest
{
    public class LambdaConfiguration : ILambdaConfiguration
    {
        public static IConfigurationRoot Configuration => new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables()
            .Build();

        IConfigurationRoot ILambdaConfiguration.Configuration => Configuration;
    }
}

```

We can now make use of this in our code as follows, we’ll edit our SpeakService to make use of the of the environment variable.

```csharp
using Microsoft.Extensions.Options;

namespace Threenine.ConfigTest.Services
{
    public class SpeakService : ISpeakService
    {
        private readonly Greeting _greeting;
      
        public SpeakService(IOptions<Greeting> hello)
        {
            _greeting = hello.Value;
           
        }

        public string Greeting => string.Concat( _greeting.Message, " ", System.Environment.GetEnvironmentVariable("SaySomething"));
    }
}


```

If we build, deploy and invoke our lambda this will work fine. However, I’m sure the [clean coders](https://dev.to/gary_woodfine/book-review--clean-code-40ki-temp-slug-6981555) amongst you will be thinking that this is dirty and we have polluted the code base a little.

### Adding Environment Variables to Dependency Injection

Next we’ll create a class that we will use to store the environment variable, we will make available to the classes in which will make use of it via dependency injection.

In this case it’s a very simple class which is going t have a property we will make use of later.

```csharp

namespace Threenine.ConfigTest.Config
{
    public class SpeakEnvironment
    {
        public string SaySomething { get; set; }
    }
}

```

The .net core framework enables us to really easily now configure and bind these variables at runtime using the [Environment Variables Configuration Provider](https://docs.microsoft.com/en-gb/aspnet/core/fundamentals/configuration/index?view=aspnetcore-2.2#environment-variables-configuration-provider) , all that we now really do is rename our Environment Variable in our serverless.yaml to include the name of our Class and a double underscore

> When working with hierarchical keys in environment variables, a colon separator (:) may not work on all platforms (for example, Bash). A double underscore (\_\_) is supported by all platforms and is replaced by a colon.

```javascript
service: Hello-Configuration

provider:
  name: aws
  runtime: dotnetcore2.1
  environment:
    SpeakEnvironment__SaySomething: "Eating coconuts is cool"
  
package:
  individually: true

functions:
  hello:
    handler: HelloConfiguration::Threenine.ConfigTest.Functions.Speak::Greet


    package:
      artifact: bin/release/netcoreapp2.1/hello.zip


```

Modify the StartUp class to configure the environment variables and wire them up for Dependency Injection we do this on line 20, which is similar to what we did previously.

```csharp
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Threenine.ConfigTest.Config;
using Threenine.ConfigTest.Services;

namespace Threenine.ConfigTest
{
    public class StartUp
    {
         public static IServiceCollection Container => ConfigureServices(LambdaConfiguration.Configuration); 
                
        
                private static IServiceCollection ConfigureServices(IConfigurationRoot root)
                {
                    var services = new ServiceCollection();
                    services.Configure<Greeting>(options =>
                        root.GetSection("greeting").Bind(options));
                    
                    services.AddTransient<ISpeakService, SpeakService>();
                    services.Configure<SpeakEnvironment>(options => root.GetSection("SpeakEnvironment").Bind(options));
                   return services;
        
                }
    }
}



```


### Additional Configuration Options

The above example works great, however you may have still spotted an additional concern. Perhaps you’re thinking this is great but what if you wanted to have different configuration options for your specific environments. For instance what if you wanted data that is created in your staging environment be redirected to different tables or queues than the ones you use in the Production ?

Fortunately, the Serverless Framework provides a super simple option, a configuration for your serverless.yml. By convention, this is typically implemented by creating an additional env.configs.yml

Typically you’ll use this file to create Environment Specific configuration information or sensitive information. For instance, you may want to store your AWS Account ID or even version or feature information.

This file will most likely not be stored in your Source Code Repository and will probably be managed by your DevOps process. However, in my case I included it in the repo to provide a sample.

I’ll create a simple file to provide a general idea:



```javascript
feature: <feature_name>
version: 1.0.0.0
region: <aws_region>
accountId: <aws_account_id>
something: "Coconuts are cool to eat"

```

In our case we created a variable which we name something and provided an arbitrary value. We can now edit our serverless.yml to make use of this file

```javascript

service: Hello-Configuration

provider:
  name: aws
  runtime: dotnetcore2.1
  environment:
    SpeakEnvironment__SaySomething: ${file(env.configs.yml):something}
  
package:
  individually: true

functions:
  hello:
    handler: HelloConfiguration::Threenine.ConfigTest.Functions.Speak::Greet

    package:
      artifact: bin/release/netcoreapp2.1/hello.zip

```

### Summary

We now have an easy to configure Lambda and the ability to create environment variables within our Serverless.yaml and consume them in our .net core lambda.