Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use ASP.NET Core App Settings with Simple Injector

I am new to ASP.NET Core and need some direction. I am trying to figure out a simple scenario with using app settings in ASP.NET Core while also using Simple Injector.

I first set up my Strongly-Type configuration settings as explained here by Rick Strahl. This works great.

  public class MySettings
  {
    public string ApplicationName { get; set; }
  }

appsetting.json

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "MySettings": {
    "ApplicationName": "Test Service"
  }
}

Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
      // Add framework services.
      services.AddMvc();

      // Add Options
      services.AddOptions();

      // Add our Config object so it can be injected
      services.Configure<MySettings>(Configuration.GetSection("MySettings"));
      services.AddSingleton(GetTestBroker(container));

      //Simple Injector       
      //services.AddSingleton<IControllerActivator>(new SimpleInjectorControllerActivator(container));
      //services.AddSingleton<IViewComponentActivator>(new SimpleInjectorViewComponentActivator(container));


  }

In our other projects were are using Simple Injector for DI. After adding the Simple Injector package and configuring it per the instructions I see that my IOptions configuration breaks.

What I'd like to know is what would be best practice for implementing a configuration in ASP.NET Core and using another DI library like Simple Injector together?

like image 302
Eric Avatar asked Feb 02 '17 21:02

Eric


People also ask

Does ASP.NET Core support dependency injection?

ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies.

What is Simpleinjector?

Simple Injector is an easy-to-use Dependency Injection (DI) library for . NET that supports . NET Core, Xamarin, Mono and Universal apps. Simple Injector is easily integrated with frameworks such as Web API, MVC, WCF, ASP.NET Core and many others.

How does ASP.NET Core dependency injection work?

Dependency injection is at the core of ASP.NET Core. It allows the components in your app to have improved testability. It also makes your components only dependent on some component that can provide the needed services. If another service depends on DataService , they are dependent on this particular implementation.

Does simple injector replace the built-in container in ASP NET Core?

NOTE: Please note that when integrating Simple Injector in ASP.NET Core, you do not replace ASP.NET’s built-in container, as advised by the Microsoft documentation.

How to create a web application using ASP NET Core?

Select the ".Net Core" and "ASP.NETCore 3.1" version and then select "Web application" as a project template. Select the appsettings.json file and add the configuration settings. Here i have added two configuration settings "ConnectionStrings" and "EmailSettings".

Does ASP NET Core support dependency injection?

Support for dependency injection is included in ASP.NET Core. As a result, you can inject both framework and application services into your classes rather than depend on tightly coupled components. Simple Injector is a free, fast, and flexible inversion of control library that is easy to use and configure.

Where are the application settings located in ASP NET Core?

In ASP.NET Core Application, all the Application settings are now located in appsettings.json file instead of app.config/web.config file. Here is what the default appsettings.json file looks like, though I have also added an AppSettings section, as shown below.


1 Answers

The ASP.NET Core integration guide for Simple Injector states the following:

.NET Core contains a new configuration model based on an IOptions<T> abstraction. We advise against injecting IOptions<T> dependencies into your application components. Instead let components depend directly on configuration objects and register those objects as instances (using RegisterInstance). This ensures that configuration values are read during application start up and it allows verifying them at that point in time, allowing the application to fail fast.

Letting application components depend on IOptions<T> has some unfortunate downsides. First of all, it causes application code to take an unnecessary dependency on a framework abstraction. This is a violation of the Dependency Inversion Principle, which prescribes the use of application-tailored abstractions. Injecting an IOptions<T> into an application component makes such component more difficult to test, while providing no additional benefits for that component. Application components should instead depend directly on the configuration values they require.

Second, IOptions<T> configuration values are read lazily. Although the configuration file might be read upon application start up, the required configuration object is only created when IOptions<T>.Value is called for the first time. When deserialization fails, because of application misconfiguration for instance, such error will only be appear after the call to IOptions<T>.Value. This can cause misconfigurations to stay undetected for much longer than required. By reading—and verifying—configuration values at application start up, this problem can be prevented. Configuration values can be injected as singletons into the component that requires them.

To make things worse, in case you forget to configure a particular section (by omitting a call to services.Configure<T>) or when you make a typo while retrieving the configuration section (e.g. by supplying the wrong name to Configuration.GetSection(name)), the configuration system will simply supply the application with a default and empty object instead of throwing an exception! This may make sense when building framework or third-party components, but not so much for application development, as it easily leads to fragile applications.

Because you want to verify the configuration at start-up, it makes no sense to delay reading it, and that makes injecting IOptions<T> into your application components sub optimal, to say the least. Depending on IOptions<T> might still be useful when bootstrapping the application, but not as a dependency anywhere else in your application. The IOptions<T> architecture is designed for the framework and its components, and makes most sense in that particular context—not in the context of line-of-business applications.

Once you have a correctly read and verified configuration object, registration of the component that requires the configuration object is as simple as this:

MyMailSettings mailSettings =
    config.GetSection("Root:SectionName").Get<MyMailSettings>();

// Verify mailSettings here (if required)

container.Register<IMessageSender>(
    () => new MailMessageSender(mailSettings));
like image 88
Steven Avatar answered Sep 26 '22 02:09

Steven