1

I am exposing a view on a new API, and want to know how I can set a default value to a property, reading it from my appsettings.json file. How can I do it?

I've tried using dependency injection on the view, but it seems impossible since it's the framework that instantiate the class.

public class FilteringRequest
    {
        private readonly IAppContext appContext;

        public FilteringRequest(IAppContext appContext)
        {
            this.appContext = appContext;
        }

        // TODO: appsettings?
        // Perhaps something like appContext.DefaultType
        public string Type { get; set; } = "top_rated";

        // ...
}

This approach doesn't work since I believe the framework is expecting a parameterless default constructor.

An unhandled exception occurred while processing the request.
InvalidOperationException: Could not create an instance of type 'Wanderlust.API.Models.Requests.FilteringRequest'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the 'request' parameter a non-null default value.
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext bindingContext)

Bear in mind that IAppContext already has all the properties defined in appsettings.json file.

Nelson Sousa
  • 497
  • 6
  • 14

2 Answers2

0

Dependency injection should work. In Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.Configure<MyAppContext>(Configuration.GetSection(nameof(MyAppContext)));
    // ...
}

Define your class MyAppContext:

public class MyAppContext
{
    public MyAppContext()
    {
    }

    public string DefaultType { get; set; }
    // other public properties here...
}

In your FilteringRequest class:

public class FilteringRequest
{
    private readonly MyAppContext _appContext;

    public FilteringRequest(Microsoft.Extensions.Options.IOptions<MyAppContext> appContext)
    {
        _appContext = appContext.Value;
    }

    string _type;
    public string Type
    {
        get => _type ?? (_type = _appContext.DefaultType);
        set => _type = value;
    }
    // ...
}
Bigabdoul
  • 721
  • 6
  • 12
  • I don't know what IOptions does, but I got this error: Error CS0310 'AppContext' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TOptions' in the generic type or method 'IOptions' – Nelson Sousa Sep 12 '19 at 18:45
  • IOptions is used to retrieve configured instances of classes that map to configuration options defined in the appsettings.json file, and other sources as well. You said "IAppContext already has all the properties defined in appsettings.json file". Since IAppContext is an interface (I suppose), there should be a concrete class that implements this interface (AppContext for example). This concrete class must have a public parameterless constructor. – Bigabdoul Sep 12 '19 at 22:05
  • By the way, I suggest you rename your "AppContext" class to something like "MyAppContext" or so because .NET already contains a static AppContext in the System namespace. – Bigabdoul Sep 12 '19 at 22:08
  • Hi Bigabdoul, I took a look at your answer but wasn't able to get it working. I've created a new simple project to illustrate my problem. Please take a look here [link](https://github.com/NelsonPRSousa/dependency-injection-default-constructor). As you can see, you must have a parameterless constructor, so I can't not use DI directly. – Nelson Sousa Oct 13 '19 at 21:15
0

To read data from appsettings.json in any class, you just need to pass Configuration with dependency injection by creating IConfiguration field:

public class FilteringRequest
{       
    private readonly IConfiguration _configuration;

    public FilteringRequest(IConfiguration configuration)
    {
        _configuration = configuration;
        Type = _configuration["Model:FilteringRequest:Type"];//set value from appsettings.json file
      
    }
 
    public string Type { get; set; } 

    // ...
}

appsettings.json:

{
"Model": {
  "FilteringRequest": {
    "Type": "testdata"
  }
}
}

Controller:

public class HomeController : Controller
{      
    private readonly IConfiguration _configuration;
    public HomeController (IConfiguration configuration)
    {
        _configuration = configuration;
    }
    public IActionResult Index
    {
        var modelinstance = new FilteringRequest(_configuration);//create the viewmodel with default 'Type"
        return View();
    }
}

Refer to :

Getting value from appsettings.json in .net core

Read appsettings.json from a class in .NET Core 2

Daz
  • 2,833
  • 2
  • 23
  • 30
Ryan
  • 19,118
  • 10
  • 37
  • 53
  • I am not using Views, it is a simple API. I've created a simple project to illustrate my problem here: [link](https://github.com/NelsonPRSousa/dependency-injection-default-constructor). Based on this, I am assuming that I must have a parameterless constructor and therefore, can't have DI – Nelson Sousa Oct 13 '19 at 21:16