.NET CORE ASYNC CONSOLE APPS

.NET CORE ASYNC CONSOLE APPS

Not Your Dad's .NET!

Microsoft Architect David Fowler called the Generic Host model a Hidden Gem, and I agree. The ability to use the same constructor based dependency injection model common to ASP.NET Core in Console Apps makes for easier testing, secret storing and configuration. It means that your microservice or serverless app, can use many of the same patterns and architecture you use when developing in ASP.NET Core.

So, how does it work? I'll walk through the process of creating a small API Library with Visual Studio Code and the .NET CORE CLI. This method should work on Mac, PC, or Linux. Even if you are on a PC, I highly recommend trying this out. All of the configuration for .NET CORE can be done outside of Visual Studio these days. Even though my day-to-day workflow includes VS 2017, I usually use a hybrid approach where I have VS Code open for various tasks.

As the diagram shows, you'll want to make sure you are using .NET Core 2.1 or higher to take advantage of the features we will be using. As you'll see, we'll also want to take advantage of C# 7.1. If this is your first time working with .NET Core download the latest .NET CORE SDK

1. Create a new .NET CORE Console App

Open Visual Studio Code and choose Open Folder. Open the Folder you want to design your new application in. Then select the View menu and open then Terminal. In the terminal type in the following lines:

dotnet new sln --name ApiTester
dotnet new console --name Api.ConsoleApp
dotnet new classlib --name Api.Library
dotnet sln add .\Api.ConsoleApp\Api.ConsoleApp.csproj
dotnet sln add .\Api.Library\Api.Library.csproj
dotnet restore
dotnet run .\ApiTester.sln --project .\Api.ConsoleApp\

If you see Hello World! repeated back to you, you're in!

The Visual Studio .sln file on Mac / Linux allows you to run dotnet restore and target all the projects in the Solution at the same time. For Window's users it gives you a .sln file you can open Visual Studio 2019.

vs-code

2. Main is Async These Days

So, now we'll need to add the Hosting package:

dotnet add .\Api.ConsoleApp\Api.ConsoleApp.csproj package  Microsoft.Extensions.Hosting

and update your Api.ConsoleApp/Program.cs to the following:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading.Tasks;

namespace Api.ConsoleApp
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var host = new HostBuilder()
            .ConfigureHostConfiguration(configBuilder => {
                // TODO
            })
            .ConfigureServices((hostContext, services) => {
                // TODO
            })
            .Build();
            await host.RunAsync();
        }
    }
}

If you try building and running this with:

dotnet run .\ApiTester.sln --project .\Api.ConsoleApp\

you'll most likely get in error:

error CS1983: The return type of an async method must be void.

At the time of writing this, the default version of C# is still 7.0.

If you were in Visual Studio 2017, you'd have to do some mousing around to set this straight. But luckily, in VS Code this is straightforward. Just update the Api.ConsoleApp.csproj to use C# 7.1

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <LangVersion>7.1</LangVersion>
  </PropertyGroup>

Now, when you run the Console App, you'll see the Host Builder in action.

3. Using the HostBuilder

If you work at a large company, you likely have old code. Microsoft is certainly not an exception. By using the Generic HostBuilder class you are actually leap-frogging into the future, beyond where the current ASP.NET Core platform is at.

image26

This is still a bit of speculation, but it appears that the Generic Host is under development to replace the IWebHost in a future release. See for example, this post:

net-core

If you are familiar with ASP.NET Core, there isn't a Startup Class as found with Asp.NET Core. If you are interested in why that is the case. See this issue on Github. Also, you'll find that not all code is reuseable between your Console App and Asp.NET Core. The IWebHostBuilder is part of the Microsoft.AspNetCore.Hosting.Abstractions library. Unfortunately, the IHost interface is found in Microsoft.Extensions.Hosting.Abstractions. This means, if you want to reuse code that uses something in the Microsoft.AspNetCore.Hosting it won't work! You'll have to end up doing some annoying copy-pasta. See https://andrewlock.net/the-asp-net-core-generic-host-namespace-clashes-and-extension-methods/ for a great discussion of this. That said, most of your business and data access layer code should be fine. More importantly, this is the direction Microsoft is at least intending to go. So, embrace it!

We will do something useful with this Console App in the next sections. Stay Tuned!

Comments