Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

To me it's just so pointless, here's an example:

    using Microsoft.Extensions.Configuration;  //extra line
    using Microsoft.Extensions.Options;    //extra line

    public class AdminController : Controller
    {
        IOptions<Settings> settings; //extra line

        public AdminController(IOptions<Settings> settings) //extra code
        {
            this.settings = settings; //extra line
        }
        

        public void RandomMethod()
        {
            var a  = settings.Value.FinallyMySetting; // 5 extra lines to access your config, genius...
        }
    }
A complete and utter waste of my time to put all those lines in, it's just pointless boilerplate trash, which C# has been getting rid of excellently, all to be undone by whoever wrote Microsoft.Extensions.Configuration. And you have to do it any where you want to get a config value.

On top of that, if you want to use it in a console app, you have to add like 5 packages. Yes, FIVE.

    <PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.9" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.9" />
    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.9" />
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.9" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.9" />

Then add this delightful mess just to initialize it:

    var environmentName = Environment.GetEnvironmentVariable("ENVIRONMENT");

    var builder = new ConfigurationBuilder()
                .AddJsonFile($"appsettings.json", true, true)
                .AddJsonFile($"appsettings.{environmentName}.json", true, true)
                .AddEnvironmentVariables();
 
    var configuration = builder.Build();
When you compare that to what any other framework does, it just beggars belief that they though this was a good way of handling config.

When I was setting this all up, I obviously hit up SO, and it's clear from many of the (incorrect) answers on SO that people just don't get it. It's too complicated for something that should be super simple.

I get that it's handy to be able to configure all that yourself, but all of that should be default and a single line/package.



I agree that there's a bit of boilerplate, but in this case it's boilerplate that's normally already handled when you're using GenericHost or WebHost builders - which will setup all this Configuration, Logging and Dependency Injection for you (take a look here for an example https://dfederm.com/building-a-console-app-with-.net-generic...). I don't know what kind of console apps you're writing, but if they require DI and environment-specific configuration files then you'd likely be better off using GenericHost. Setting all this up by hand is a bit cumbersome, but I don't think they were really intended to be used that way.


Apart from needing two namespaces, this does look reasonable to me. I'm not sure how you could make constructor-based dependency injection easier without making it less obvious what is happening. And most of the additional lines are stuff your editor can do for you, even in VS Code you can automatically generate the field and assignment and the imports after just typing the constructor parameter.

ASP.NET Core does push you strongly towards dependency injection, but it does not force you at all to use it.


> ASP.NET Core does push you strongly towards dependency injection, but it does not force you at all to use it.

Their own documentation for making queries against SQL Server doesn't provide examples of how to do it that aren't using DI. "Just inject it" it just says. Thanks .net, super helpful. Maybe the docs are there, but I couldn't find them at all when I went looking.


    using(var conn = new SqlConnection("<conn-string>"))
    using(var cmd = new SqlCommand(@"Query here", conn))
    {
      conn.Open();
      cmd.executeNonQuery();
    }


Hmmmm, maybe I am just dense hahaha.


In their defence, there is a default builder that would save you maybe 3-4 lines there, but I do generally agree with your point.

It is something that annoys me about .NET in general there is just decades of over-engineering cruft and once these practices emerge its difficult to get people to stop doing them. The problem only gets worse as time passes.


THe last time I used .net core and had to handle some config was a nightmare like you describe. The documentation wasn't great either. The whole way everything is complicated and messy made me want to just quit my job.

It's such convoluted nonsense.

I like C# but sometimes it feels like MS main aim is to make developers miserable.


> it's just pointless boilerplate trash,

I don't regard the "ConfigurationBuilder" and following lines as "boilerplate" exactly, since by not using the default HostBuilder and instead including that code, you are making choices.

Specifically, you are choosing to pull in settings from "appsettings.json", "appsettings.{env}.json" and then environment vars, in that order, and specifying that both files are optional and should reload on change.

You can make other choices, with other code.The code is there to "configure the config", i.e. to make those choices.


I'm mainly interested in one statement:

> it's just pointless boilerplate trash, which C# has been getting rid of excellently

Could you elaborate on how you feel C# avoided this?

From my point of view the only alternative (to DI with constructor injection) is static members somewhere, which does not scale. Maybe property injection, but ugh.


I think they want to use something more like an environment contextual config fetcher instead.

For example:

test.appsettings.json

{"db-url":"test.url.here"}

prod.appsettings.json

{"db-url":"prod.url.here"}

Now in the code:

Settings.fetch("db-url");

// Will return the test one if environment variable says we are running under test environment, else will return the prod one.


The DI-based configuration system can be configured to do exactly that. Though yes, the configuration is maybe harder than it should be simply because it isn't on by default.

A lot of the complexity in the configuration system exists to enable a lot of configuration options. I have some ASP.NET applications that get some configuration from Environment Variables on the host machine, some from environment-specific config files, some from a configuration service (specifically Azure Key Vault), all without any of my DI-injected downstream components specifically needing to know which source provided specifically which configuration key. For the DI injected things it is just `config["db-url"]` or maybe type-safe class if I DI-inject an IOptions<T> (or add my type-safe classes directly to the DI without the IOptions<T> wrapper, which is another configurable option).

It's absolutely a very complex system, but with great complexity comes great flexibility (to badly paraphrase the Spider-Man mantra).


Do you type every line typically? If you use Rider or VS pretty much every one of those lines can be auto generated with autocomplete. Also, this can easily be worked around. Just create a Singleton which has the settings injected into it. I prefer the testability of the injected version but if you'd rather access a static global it is very easy to do.


I do agree

I just type IOptions<T> config in ctor, use ctrl+. and private readonly property and it's initialization is generated


That doesn't work unless you already have the using statements, which you won't have as you haven't added it yet.

I just tried it.


I'm using Roslynator:

https://i.imgur.com/cWs1M77.png

and I have some naming rule

https://i.imgur.com/iPwNj5b.png

So I basically have to type IOptions<T> Name and use ctrl+. twice in order to generate private readonly property and initialize it and add using to IOptions


you can use property injection when you use something like autofac as the di container.


Cool, so I'll add another dependency and figure out how to use that, to save myself time having to write out MS's convoluted dependency-injected configuration code.


Meanwhile one could of have this solved in their projects in less than the time it took to have this HN discussion and moved on with their life. Seriously, somethings are worth complaining over, others are not.


well you don't need to use dependency injection at all. there. is no need to use IConfiguration.

also as far as I heard, is that microsoft is working on a micro web framework, that does not use di. (something like https://github.com/featherhttp/framework, just more official i guess)


Talk about Stockholm Syndrome. Classic enterprise public SomethingBuilder builder = new SomethingBuilder() ; builder.AddFanfoldConfig() ; builder.build(). Sun, Microsoft and Oracle and have hoodwinked generations into believing this kind of crap is the Rolls Royce of software development and we let them get away with it.


> When you compare that to what any other framework does

Can you show me what that looks like?


You don't need to inject IOptions, you can inject the Settings class directly. I don't see an issue with those extra lines, VS generates them with one hotkey for me.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: