6

I've got a .NET Framework console app I'm trying to update to .NET 5, but it's failing on certain points that require data from app.config.

The relevant documentation on how config works now quite helpfully has all of its examples as console apps... right up until you actually look at the examples, which are completely unhelpful. They're all based around a Main block that looks like this:

        static async Task Main(string[] args)
        {
            using IHost host = CreateHostBuilder(args).Build();

            // Application code should start here.

            await host.RunAsync();
        }

A console app isn't a WinForms app. The application code doesn't "start" in Main; Main is the main body of your program, which means that putting the line that makes configuration actually work at the end of the method means it will never be hit until the program is ready to terminate!

What am I missing? These documentation examples appear entirely pointless. I'm not trying to host any services; I just want my existing app.config to be read at startup and made available to the config system, exactly the way it used to work in .NET Framework. What's the proper way to get the old behavior back?

Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477
  • https://stackoverflow.com/questions/45851669/configuration-for-console-apps-net-core-2-0 – zaitsman Aug 25 '21 at 12:17
  • @zaitsman Yes, what about it? – Mason Wheeler Aug 25 '21 at 12:23
  • 1
    I would say that these are just examples. No need to use the `HostBuilder` if you're not hosting any services. Simply fetch the `appsettings` as suggested by @zaitsman and then execute your code. – smoksnes Aug 25 '21 at 12:40
  • @smoksnes Fetch what appsettings? I'm not fetching anything. I have a third-party dependency ([linq2db](https://github.com/linq2db/linq2db)) that's expecting the configuration info to *just be there*, and it's not working. How do I get the previous behavior back? – Mason Wheeler Aug 25 '21 at 12:47
  • @MasonWheeler, I wrote and answer, but then realized I don't fully understand the question. What is the "old behavior" you want? Could you elaborate with an example written in .NET Framework? – smoksnes Aug 25 '21 at 13:06
  • @smoksnes The old behavior is, there's an `app.config` file, the program reads it at startup, and that data is available to the config system from that point forwards. It's literally that simple -- or at least it used to be. – Mason Wheeler Aug 25 '21 at 13:13
  • 1
    @MasonWheeler, well yes. It was dependant on `ConfigurationManager` if I recall correctly. It was/is `static` and could be used everywhere. In .Net Core (or .NET5) you build your `IConfiguration` with `ConfigurationBuilder`. Then you usually register it with your DI-container (`ServiceProvider`) and inject it where you need it. Classes that depend on your registration will then inject `IConfiguration` when needed. And no. It's not exactly how it was with .NET Framework. But that's because .NET 5 isn't like .NET Framework. – smoksnes Aug 25 '21 at 13:19

2 Answers2

6

Setting up the configuration should be pretty strait forward, there are plenty more options the configuration builder offers but here is bare bones for this example.

IConfiguration config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

If you are wanting to use a DI pattern in your app then use IOptions approach, In your constructor just ask for IOptions<OptionConfig>, otherwise you could inject just IConfiguration (Don't recommend)

var serviceProvider = new ServiceCollection()
    .AddSingleton<IConfiguration>(config)
    .Configure<OptionConfig>(config.GetSection("ExampleSection"));
    .BuildServiceProvider();

Of course you will want to enter your first dependency using the service provider to essentially build your "application dependency tree"


Edit For those wanting a .net core project to work like configuration of old (.net framework).

If you want to use ConfigurationManager you can its available to developers using the Nuget Package System.Configuration.ConfigurationManager. Make sure to include the config file as app.config, the configuration should look something like this.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="appconfigtest" value="abc" />
    </appSettings>
</configuration>
Zach Hutchins
  • 801
  • 1
  • 12
  • 16
  • The problem is, I'm not trying to use it directly; it's being used by a third-party dependency, so I can't fix it by changing my code in any way that isn't related to setup of the config system. *I need it to work the way it used to work in .NET Framework.* – Mason Wheeler Aug 25 '21 at 14:21
  • @MasonWheeler Is this third-party dependency written in `.netstandard`? – Zach Hutchins Aug 25 '21 at 14:42
  • @MasonWheeler I added in an alternative on how to use ConfigurationManager in .net core. If your dependency is in .netframework though you might struggle to use it since its probably not compatible with your core project (worth a shot though) – Zach Hutchins Aug 25 '21 at 15:37
0

I suggest you could use System.Configuration.ConfigurationManager. This ConfigurationManager.ConnectionStrings is part of .NET Core Desktop runtime since .NET Core 3.0 (in previous version before 3.0, System.Configuration.ConfigurationManager was available as external nuget package).

By using System.Configuration.ConfigurationManager you can leverage existing app.config to be used for your Console project.

On your csproj of the console project, add this:

<PropertyGroup>
    <UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>

Then you could have reference to System.Configuration.ConfigurationManager,

add the using System.Configuration;

and try something like this to get first connection string from ConfigurationManager.ConnectionStrings collection:

var constring = ConfigurationManager.ConnectionStrings[0];
Eriawan Kusumawardhono
  • 4,796
  • 4
  • 46
  • 49