skip to Main Content

In my application I am using appsettings to load my configuration. I have the appsettings.json:

{
  "FileReader": {
    "InputDirectory": "tmp"
  }
}

I would like to have the option to override the value of InputDirectory with a command line argument shorthand switch (e.g. -i). I know I can override it via an environment variable named FileReader__InputDirectory, but for the SwitchMappings in my Program.cs I don’t know what value would work. Here is my code:

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration((context, builder) =>
    {
        builder
            .AddJsonFile("appsettings.json", false, false)
            .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", true, false)
            .AddEnvironmentVariables()
            .AddCommandLine(source =>
            {
                source.Args = args;
                source.SwitchMappings = new Dictionary<string, string>()
                {
                    { "-i", "FileReader__InputDirectory" } // <-- what is the correct mapping here?
                };
            });
    })
    .ConfigureServices((context, services) =>
    {
        Console.WriteLine(context.Configuration.GetSection("FileReader")["InputDirectory"]);
        services.AddHostedService<Worker>();
    })
    .Build();

When I am running dotnet run -i ./source/json I would expect the printed out value to be source/json (the value from the argument) but what I get is tmp (the value from the appsettings.json file).

If I try this without the nesting with a property on the appsettings root level it works just fine.

2

Answers


  1. Use : as delimiter:

    source.SwitchMappings = new Dictionary<string, string>()
    {
         { "-i", "FileReader:InputDirectory" } 
    };
    

    __ is substitution for : specifically for environment variables.

    Note that you can just pass it via CLI parameter (see this answer):

    dotnet run --FileReader:InputDirectory=./source/json
    

    See also:

    Login or Signup to reply.
  2. It seems the real question is how to add a new argument mapping, not how to override settings.

    All config sources are available through the ConfigurationBuilder.Sources list. The configuration code could find the existing source and change its mapping :

    .ConfigureAppConfiguration((context, builder) =>
    {
        var cliSource=builder.Sources.OfType<CommandLineConfigurationSource>();
        if(cliSource!=null)
        {
            cliSource.SwitchMappings=new Dictionary<string, string>()
                    {
                        { "-i", "FileReader:InputDirectory" }
                    };
        }
    }
    

    Remove the entire ConfigureAppConfiguration section and use --FileReader:InputDirectory in the command line to override the JSON setting.

    dotnet run --FileReader:InputDirectory=tmp
    

    The generic host configures JSON, environment variables and CLI arguments out of the box. There’s no need to add the same sources all over again.

    The Command Line arguments section in ASP.NET Core configuration shows how to pass arguments using various delimiters like --, = or /, eg :

    dotnet run /MyKey "Using /" /Position:Title=Cmd /Position:Name=Cmd_Rick
    

    or

    dotnet run --MyKey "Using --" --Position:Title=Cmd --Position:Name=Cmd_Rick
    

    In your case, you can use

    dotnet run --FileReader:InputDirectory=tmp
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search