.NET 5 Console App with Dependency Injection, Serilog Logging, and AppSettings
Tags: dotnet, beginners, dependencyinjection, consoleapp
Published: 2021-03-24 12:24:18

In this article we will be building a .Net 5 console app which support dependency injection, logging and app settings configuration.

You can watch the full Video on Youtube:

{% youtube 4mEN1XpLN_s %}

And you get the full source code on GitHub:
https://github.com/mohamadlawand087/v22-DotnetConsole

So what's in our agenda today:

- development ingredients
- the functionalities we are going to build
- Coding

Development Ingredients

- Visual Studio Code
- Dotnet Core SDK

Functionalities:

- Dependency Injection
- Serilog Logger
- AppSettings.

We are going to build a sample application which will mimic connecting to a database through dependency injection as well as outputting logs.

We will start by creating our application, inside our terminal

```bash
dotnet new console -n "SampleApp"
```

Once the application has been create, open the application in Visual Studio Code and let us build and the application to make sure everything is working.

```bash
dotnet build
dotnet run
```

The next step is installing the packages that we need.

```bash
dotnet add package Microsoft.Extensions.Hosting
dotnet add package Serilog.Extensions.Hosting
dotnet add package Serilog.Settings.Configuration 
dotnet add package Serilog.Sinks.Console
```

The next step will be adding our appsettings.json, to do that in root directory of our application right-click select New File. Name the file appsettings.json

Inside the appsettings we are going to add all of the configuration that we need to setup serilog as well as the connectionString to mimic a database connection

```json
{
    "Serilog" : {
        "MinimalLevel": {
            "Default": "Information",
            "Override": {
                "Microsoft": "Information",
                "System": "Warning"
            }
        }
    },
    "ConnectionStrings": {
        "DefaultConnection": "DataSource=app.db;Cache=Shared"
    }
}
```

We will start by implementing the logging mechanism. Inside our Program.cs Add the following code, this code responsibility is reading the appsetting.json and making it available to our application.

```csharp
static void BuildConfig(IConfigurationBuilder builder)
{
    // Check the current directory that the application is running on 
    // Then once the file 'appsetting.json' is found, we are adding it.
    // We add env variables, which can override the configs in appsettings.json
    builder.SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddEnvironmentVariables();
}
```

Now we need to create another method which will be out startup method for our application, it will responsible to put everything together. We will define Serilog as well our dependency injection mechanism in .Net Core.

```csharp
static IHost AppStartup()
{
    var builder = new ConfigurationBuilder();
    BuildConfig(builder);

    // Specifying the configuration for serilog
    Log.Logger = new LoggerConfiguration() // initiate the logger configuration
                    .ReadFrom.Configuration(builder.Build()) // connect serilog to our configuration folder
                    .Enrich.FromLogContext() //Adds more information to our logs from built in Serilog 
                    .WriteTo.Console() // decide where the logs are going to be shown
                    .CreateLogger(); //initialise the logger

    Log.Logger.Information("Application Starting");

    var host = Host.CreateDefaultBuilder() // Initialising the Host 
                .ConfigureServices((context, services) => { // Adding the DI container for configuration

                })
                .UseSerilog() // Add Serilog
                .Build(); // Build the Host
    
    return host;
}
```

Now let us implement data service which will mimic a database

Let us create a new class called DataService and an interface called IDataService

```csharp
// Interface
public interface IDataService
{
     void Connect();
}

// Class
public class DataService : IDataService
{
    private readonly ILogger<DataService> _log;
    private readonly IConfiguration _config;
    public DataService(ILogger<DataService> log, IConfiguration config)
    {
        _log = log;
        _config = config;
    }

    public void Connect()
    {
        // Connect to the database
        var connectionString = _config.GetValue<string>("ConnectionStrings:DefaultConnection");
        
        _log.LogInformation("Connection String {cs}", connectionString); 
    }
}
```

Now we need to update our AppStartup method in the Program.cs class to inject the DataService

```csharp
var host = Host.CreateDefaultBuilder() // Initialising the Host 
                .ConfigureServices((context, services) => { // Adding the DI container for configuration
                    **services.AddTransient<IDataService, DataService>(); // Add transiant mean give me an instance each it is being requested.**
                })
                .UseSerilog() // Add Serilog
                .Build(); // Build the Host
```

And finally let us put everything together in our main method

```csharp
static void Main(string[] args)
{
    var host = AppStartup();

    var service = ActivatorUtilities.CreateInstance<DataService>(host.Services);

    service.Connect();
}
```

Please let me know if you want me to jump into more details about any part of this application or if there is a specific feature which you would like me to cover.

Thanks for reading