# .NET Core

## Getting and publishing a function

The following shows how to get, edit, and pack your template for upload.

| Versions      | Template                                                                                            |
| ------------- | --------------------------------------------------------------------------------------------------- |
| .NET Core 2.1 | [Download](https://codemash-public.s3.eu-central-1.amazonaws.com/code-templates/dotnetcore_2_1.zip) |

* After you have downloaded the template project, unzip it and navigate to `./LambdaFunction` directory and open `LambdaFunction.csproj` project (if you are not using an IDE with automated restore functionality, run `dotnet restore` in command-line tool inside this folder).
* Your entry (main) method will be inside `Function.cs` file called `Handler`.
* After you are done editing your function, open command-line tool inside of `./LambdaFunction`

  &#x20;directory and run`dotnet publish -o lambda`.
* Navigate to a newly created folder `./lambda` and zip all the contents inside of the directory.
* Upload zipped file to CodeMash.

For the **handler,** you have to specify your entry function location. Handler follows such format - `assembly::namespace.className::methodName`. Following the structure given in the initial template, the handler would be `LambdaFunction::LambdaFunction.Function::Handler`. You can edit any of these parameters for your own function.

## Template overview

The following explains how to use provided template to create your own functions.

### Main method

You define your main function in the handler field. In this case, the main method is `Handler`. It takes two parameters - input from CodeMash and function configuration.

```csharp
public async Task<APIGatewayProxyResponse> Handler(CustomEventRequest<BasicInput> lambdaEvent, ILambdaContext context)
{
    ...
}
```

### Inputs

CodeMash will always return `CustomEventRequest` as an input object. This class takes in generic parameter defining one of the possible input type. The following table explains when to use each of the provided inputs.

| Class                    | Description                                                                         |
| ------------------------ | ----------------------------------------------------------------------------------- |
| `BasicInput`             | Use when executing function through API or using this function in a scheduler task. |
| `CollectionTriggerInput` | Use when using this function as a trigger for collections.                          |
| `FileTriggerInput`       | Use when using this function as a trigger for files.                                |
| `UserTriggerInput`       | Use when using this function as a trigger for users.                                |

### Getting environment variables

A line below shows how to get the environment variables that you have set up near your function.

```csharp
var envVariable = Environment.GetEnvironmentVariable("myVariableName");
```

### Getting app settings

If you want to user`appsettings.json`file the following shows how to read a file. In this case, file is in root directory of a project.

```csharp
public static class AppSettings
{
    private static IConfigurationRoot instance;

    // Method to get a string from settings
    public static string GetString(string key)
    {
        if (instance == null)
        {
            // Create an instance with settings
            instance = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .Build();
        }
        
        // Get value by key
        return instance[key];
    }
}
```

Example of a `appsettings.json` file:

```csharp
{
    "Parameter1": "First parameter.",
    "NestedParams": {
        "NestedParam1": "First nested parameter."
    }
}
```

Then to get a string from settings:

```csharp
// First level parameter
var settings = AppSettings.GetString("Parameter1");

// Second level parameter
var nestedSettings = AppSettings.GetString("NestedParams:NestedParam1");
```

### Constructors

Lambda executor will call your default constructor (without parameters). If you want to add dependency injection to your services, you will have to add a default constructor which calls your wanted constructor.

```csharp
public class Function
{
    private readonly IExampleService _exampleService;
    
    // (Required if adding other constructors. Otherwise, optional.) A default constructor
    // called by Lambda. If you are adding your custom constructors,
    // default constructor with no parameters must be added
    public Function() : this (new ExampleService()) {}

    // (Optional) An example of injecting a service. As a default constructor is called by Lambda
    // this constructor has to be called from default constructor
    public Function(IExampleService exampleService)
    {
        _exampleService = exampleService;
    }
    
    public async Task<APIGatewayProxyResponse> Handler(CustomEventRequest<BasicInput> lambdaEvent, ILambdaContext context)
    {
        ...
        
        // - Call example service
        var helloWorldMessage = await _exampleService.GetHelloWorld();
        
        ...
    }
}
```
