The most common .net core applications I end up developing are Console Applications because they are by far the most useful applications and their usage expands far further than simply writing text out to a terminal window.
For instance, they are essentially the basis for developing Linux Daemons or if you're using - TopShelf: An easy service hosting framework for building Windows services using .NET. - you can quickly and easily build Windows Service applications.
Using the Console application template that ships with the .net core, generates a stripped down basic application with absolute minimum references required for an application. This leads to some confusion among developers as to what references they need to import to get the same features which are commonly found in other application generation templates.
In this post, I will walk you through the steps involved to make use of a JSON Application settings file to store and retrieve application configuration settings in a .net core console application.
Configuration API in ASP.NET Core
The .NET core framework comes with a comprehensive Configuration API which provides a mechanism to configure a .NET Core application based on a list name-value
Name-Value
There are configuration providers for:
- File formats (
INI, JSON, and XML
) - Command-line arguments
- Environment variables
- In-memory .NET objects
- Unencrypted Secret Manager storage
- Encrypted user store, such as Azure Key Vault
- Custom providers
The configuration API really simplifies using configuration files and comes with some really good features.
Generate a console application in .net core
We will build a trivial Console Application in .Net core to walk through the process of using Configuration API. The application itself, will be mostly irrelevant and serve no real purpose, other than to illustrate how to make use of the configuration API, a simple FizzBuzz algorithm and the Configuration aspect of the application enables the configuration of string values for Fizz and Buzz to be replaced by a string of choice by system configuration.
How to create console application in .net core
I usually develop .net core applications on Ubuntu and predominantly use JetBrains Rider - cross platform .NET IDE, therefore I generally use the terminal window commands to generate the application. However, Rider does have a project template to generate Console applications.
For the purpose of this tutorial, and in order to keep things transparent and easy to follow with know dependencies on any IDE's etc, we will build everything making use of terminal commands.
To generate a console application in .net core we'll use the dotnet new <application type>
command a with a couple of option switches. For a full list of available switches and options you can use the dotnet help
.NET Core SDK (3.1.101) Usage: dotnet [runtime-options] [path-to-application] [arguments] Execute a .NET Core application. runtime-options: --additionalprobingpath <path> Path containing probing policy and assemblies to probe for. --additional-deps <path> Path to additional deps.json file. --fx-version <version> Version of the installed Shared Framework to use to run the application. --roll-forward <setting> Roll forward to framework version (LatestPatch, Minor, LatestMinor, Major, LatestMajor, Disable). path-to-application: The path to an application .dll file to execute. Usage: dotnet [sdk-options] [command] [command-options] [arguments] Execute a .NET Core SDK command. sdk-options: -d|--diagnostics Enable diagnostic output. -h|--help Show command line help. --info Display .NET Core information. --list-runtimes Display the installed runtimes. --list-sdks Display the installed SDKs. --version Display .NET Core SDK version in use. SDK commands: add Add a package or reference to a .NET project. build Build a .NET project. build-server Interact with servers started by a build. clean Clean build outputs of a .NET project. help Show command line help. list List project references of a .NET project. msbuild Run Microsoft Build Engine (MSBuild) commands. new Create a new .NET project or file. nuget Provides additional NuGet commands. pack Create a NuGet package. publish Publish a .NET project for deployment. remove Remove a package or reference from a .NET project. restore Restore dependencies specified in a .NET project. run Build and run a .NET project output. sln Modify Visual Studio solution files. store Store the specified assemblies in the runtime package store. test Run unit tests using the test runner specified in a .NET project. tool Install or manage tools that extend the .NET experience. vstest Run Microsoft Test Engine (VSTest) commands. Additional commands from bundled tools: dev-certs Create and manage development certificates. fsi Start F# Interactive / execute F# scripts. sql-cache SQL Server cache command-line tools. user-secrets Manage development user secrets. watch Start a file watcher that runs a command when files change. Run 'dotnet [command] --help' for more information on a command.
Step 1
Create a .net core console application
# Generate the application creating a src folder and name the application FizzBuzz dotnet new console -o src -n FizzBuzz
This command generates the basic structure of an application and has just enough code to run the application but nothing else.
Let's look at the structure of the project file:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> </Project>
As you can tell there is basically a reference to the Target Framework
and that is about it. No other dependencies have been added.
Taking a look at Program.cs
file we'll see that the only thing the application can do at this point is print out "Hello World!"
to the terminal.
using System; namespace FizzBuzz { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } } }
How to run .net Core console app from the command line
Its possible to Pass arguments to a console application when running it from a command line. If we alter the code slightly to use any arguments passed in.
The Main method is the entry point of a C# Application, typically when an application is started the Main method is the first method that is invoked.
There can only be one entry point in a C# Program.
The Main
method can be declared with or without a string[]
parameter that contains command-line arguments.
Parameters are read as zero-indexed command-line arguments. Unlike C and C++, the name of the program is not treated as the first command-line argument in the args
array, but it is the first element of the GetCommandLineArgs()
method.
using System; namespace FizzBuzz { class Program { static void Main(string[] args) { Console.WriteLine($" Hello {args[0] } !"); } } }
We can now create application stubs with the command dotnet build
and then execute the FizzBuzz.dll in bin/Debug//netcoreapp3.1/
or we can now execute the application using the command dotnet FizzBuzz "Gary"
and we should see the following result:
$ dotnet bin/Debug/netcoreapp3.1/FizzBuzz.dll "Gary" # This should result in Hello Gary !
This works great if you want to pass in additional arguments to a Console application, for instance, we could configure our simple Console application to run as a Linux daemon, by creating what is commonly called systemd user units.
#Tell systemd which program to start ExecStart=/usr/local/bin/dotnet /opt/daemons/fizzbuzz/FizzBuzz.dll "Gary" [Unit] Description= FizzBuzz Service [Service]
The above process is one way to pass configuration or data that the application may require to run. For instance, you may want to pass in a Url string you want the application to run or any other crucial information that may be needed.
Step Two
The above approach does obviously come with some restrictions and obviously some security and operational concerns. It is highly likely that you may want to be able to supply other information to your application.
This is where the .net core Configuration API comes into play, which provides different ways of configuring any application based on a list of name pair values which can also be read from different types of sources. This name value pair can be grouped into a multi-level hierarchy.
.net core provides configuration providers for:
- File Format (
.ini, .json and .xml
) - Command Line arguments
- Environment Variables
- In memory .net objects
- Encrypted User store
- Custom Providers
Adding a Reference to the Configuration API
In order to enable our Console Application to read Configuration from files we will need to add a reference to the following libraries
- Microsoft.Extensions.Configuration - enables key-value pair based configurations
- Microsoft.Extensions.Configuration.FileExtensions - Extension methods for configuring file-based configuration providers
- Microsoft.Extensions.Configuration.Json - JSON configuration provider
dotnet add package Microsoft.Extensions.Configuration dotnet add package Microsoft.Extensions.Configuration.FileExtensions dotnet add package Microsoft.Extensions.Configuration.Json
Once the references have been added, we can simply do a dotnet restore
to ensure they are added to your project.
In previous versions of .net application configuration settings were stored in an XML based file known as either app.config or web.config depending on the type of application that was being developed. These files were used to store application configuration settings such as database connection strings, any application scope global variables and many more application specific settings.
In .net core and future versions of .net this has now been replaced by the appsettings.json
What is the appsettings.json file
The appsettings.json
file contains configuration settings for the application in a JSON format. It is possible to read and access the configuration settings from application code by making use of the IConfiguration
Create a simple appsettings.json
to store our configuration settings, by just add a plain JSON file into the root of you application and name it appsettings.json. Professional IDE's like Rider and others will have a short cut to add one.
For the purpose of this demonstration lets add just one name/value pair to the file with the following code:
{ "name" : "Gary" }
Edit the .csproj
file and add the following lines to the file.
These lines will ensure that the appsettings.json
file will be copied to the Output Directory property. To ensure we copy the most up to date version of the file set it toPreserveNewest
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> <ItemGroup> <None Update="appsettings.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> </Project>
We have ensured that the configuration file into the working directory, we can just refer to it by name without providing a directory path.
We now need to import the 3 libraries we referenced to our Console Application.
using System; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.FileExtensions; using Microsoft.Extensions.Configuration.Json;
Once they are referenced we can now utilise them in our application. We'll slightly ammend our Main
method to read our new appsettings.json
file.
IConfiguration config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", true, true) .Build();
Once this has been done we can now now simply read the contents of our config file. Lets update the Console.WriteLine
to write the name that is stored in our Configuration File.
Your app settings file will look like this
{ "name" : "Gary" }
We are now able to access the data stored in our json
file via a Name-Value
key pairing
Console.WriteLine($" Hello { config["name"] } !");
The completed code should look as follows
using System; using System.IO; using Microsoft.Extensions.Configuration; namespace FizzBuzz { class Program { static void Main(string[] args) { IConfiguration config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", true, true) .Build(); Console.WriteLine($" Hello { config["name"] } !"); } } }
Running the application we will get to see the following printed out to the command line
Hello Gary !
This works great for really simple Configuration Options and really simple applications. However, if we start getting into more complex application scenarios and we want to split our configuration options up into sections with strongly typed access, that we will ideally use for different sections of the application. We can easily extend up this option.
Step Three
The features highlighted above illustrate how easy and flexible it can be to use Configuration API in a .net core console applications. However, you may be thinking it's a little clunky and there is a little danger of overuse of Magic Strings and make your code a little verbose.
To learn more about minimising the use of Magic Strings and Numbers within your code, I recommend reading Philosophy of Software Design Although the book is mostly about Java, you'll find that many of the suggestions pertain just as much to C#.
A Philosophy of Software Design
how to decompose complex software systems into modules that can be implemented relatively independently.
Using Strongly typed configuration in .net core console application
Ideally you would want to make use of Strongly typed configuration serialised classes. In order to do this we will need to make use of Depenedency Injection.
In order to achieve this we will nee to add an additional reference, to the Microsoft.Extensions.Configuration.Binder
, a Static helper class that allows binding strongly typed objects to configuration values.
dotnet add package Microsoft.Extensions.Configuration.Binder
We now create a couple of additional classes, one for our Application
settings and another to for the actual App
we're going to run.
We can now serialise the class, using the Get
method of the Binder extensions. In order to do lets create a class with a some properties that we would like populated. Lets create a Hello class with a name property.
We will also add an additional nuget package to help with serialising/deserialising JSON files, NewtonSoft.Json a popular high-performance JSON framework for .NET.
dotnet add package Newtonsoft.Json
We can now create a new class which well put in a new directory in our application called Model and name the file Application.cs
[JsonObject("application")] public class Application { [JsonProperty("name") public string Name {get;set;} }
We can then edit out AppSettings file adding the section that looks something like this
{ "application": { "name": "Gary" } }
We can then bind the information in the following manner.
using System; using System.IO; using FizzBuzz.Models; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Binder; namespace FizzBuzz { class Program { static void Main(string[] args) { // You could either use this var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build(); // Or this approach to get your configuration IConfiguration config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", true, true) .Build(); // Then get your values using this approach var appConfig = builder.GetSection("application").Get<Application>();; Console.WriteLine($"Application Name : {appConfig.Name}"); } } }
Summary
In this post we covered the basic of how to use Configuration API in a .net core console application to store and retrieve Application Configuration data.
This dramatically simplifies your approach. However this is still not the optimum approach and in a forthcoming post we will look at using strongly typed configuration in .NET Core console application but before that we will need to discuss Dependency Injection in .net core.
- What is this Directory.Packages.props file all about? - January 25, 2024
- How to add Tailwind CSS to Blazor website - November 20, 2023
- How to deploy a Blazor site to Netlify - November 17, 2023