0

I'm trying to pass command line arguments to Startup class. Following this example, I modified my Program class and it looks like this:

        var builder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("generalsettings.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables(prefix: "ASPNETCORE_")
            .AddCommandLine(args);  
        var config = builder.Build();

        var host = new WebHostBuilder()
            .UseUrls("http://*:5000")
            .UseConfiguration(config)
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();

        host.Run();

generalsettings.json contains following data:

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Therefore I commented out default Startup class' constructor. Then I noticed that that's where IConfigurationRoot Configuration is assigned, and therefore, when I'm trying to use it from ConfigureServices it's null. I'm trying to use (I think) configuration built in Program's Main. What am I missing here?

UPDATE

To make it clear: I'm trying to use args in Startup class.

Community
  • 1
  • 1
nicks
  • 2,161
  • 8
  • 49
  • 101
  • What exactly are you trying to accomplish here. I feel like what I think you are trying to do could be accomplished using your launchSettings.json. Which should be in your Properties for the project. – Patrick Mcvay Dec 01 '16 at 20:41
  • I'm trying to use `args` in `Startup` file. – nicks Dec 02 '16 at 20:33

1 Answers1

4

It turns out that there has been a fair amount of discussion about this sort of thing in GitHub Aspnet hosting repo issues area. The GitHub repositories are always a good place to look on an interesting problem like this one.

To sum things up for you, do not set up IConfigurationRoot in Program.Main, set it up in Startup. You can pass the command line arguments to the Startup constructor from Program.cs like so:

    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .ConfigureServices(services => services
                .AddSingleton(new ConsoleArgs(args))
            )
            .Build();
        host.Run();
    }

where ConsoleArgs is a holder class you can create yourself that looks like:

public class ConsoleArgs
{
    public ConsoleArgs(string[] args)
    {
        Args = args;
    }
    public string[] Args { get; }
}

Obviously, configuring a ConsoleArgs service is the key. This will allow it to be injected into the Startup constructor. Then your Startup class constructor looks something like

public Startup(IHostingEnvironment env, ConsoleArgs args)
{
     var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("generalsettings.json", optional: false, reloadOnChange: true)
    .AddEnvironmentVariables(prefix: "ASPNETCORE_")
    .AddCommandLine(args.Args);  
    var config = builder.Build();
}

The pattern here is "configure you hosting environment Program, configure you application in Startup"

GlennSills
  • 3,977
  • 26
  • 28
  • that passed `args` correctly, but on `Configuration = builder.Build();` exception was thrown, saying that `Unrecognized argument format: 'asdf'.` ("asdf" being argument that I passed for testing). – nicks Dec 05 '16 at 07:25
  • however, when I changed argument to asdf=eee, it compiled okay. is that because arguments should be in dictionary (key-value) format? – nicks Dec 05 '16 at 07:27
  • yeah, there are some assumptions made in the naming of configuration keys. Since key/value defined in JSON get overridden when you add an environmental variable or a command line item, and since all this stuff has to run on multiple platforms, the names of things have some restrictions. JSON is a tree structure because it represents and object, but command line args and environmental variables are obviously just key simple value. So there is a bit of magic to define an env var that overloads a JSON subobject value. See https://github.com/aspnet/Configuration for details. :-) – GlennSills Dec 06 '16 at 11:20