0

Recently i tried to create a MVC application using ASP.NET Core 2.0 and i had some values defined in appsettings.json,

"MySettings": {
"WebApiBaseUrl": "http://localhost:6846/api/"
}

In order to read these values i have added

services.Configure<MySettingsModel>(Configuration.GetSection("MySettings"));

above line in ConfigureServices method in Startup.cs and in my home controller i have added

private readonly IOptions<MySettingsModel> appSettings;
public HomeController(IOptions<MySettingsModel> app)
{
   appSettings = app;
}

MySettingsModel class is just a model with property same as key define in appsettings.json. by this method i'm able to read the value of this key.

Now my issue is that i want to use this key in many controllers so i don't want to repeat this code in every controller so what i did was i created a BaseConntroller, added its constructor and i got my values there. But when i inherit other controllers with my BaseController , it throws me an error and tells me to generate it's constructor, so basically it tells me to add constructor in every controller which is what i wanted to avoid.

How can i achieve this?

You can see the image for the error This is the error that i get

And these are the potential fixes that it shows me.

Potential fixes

ravi raghav
  • 85
  • 11
  • 1
    Having the constructor is how the framework will inject the settings into the derived class. No getting around that without using an service locator anti-pattern – Nkosi Jul 03 '18 at 10:20

2 Answers2

3

This is just basic C# inheritance. Derived classes must re-implement constructors on base classes (at least the ones you want or need). The only exception is the empty constructor, which is implicit. In other words, you simply need:

public class HomeController : BaseController
{
    public HomeController(IOptions<MySettingsModel> app)
        : base(app)
    {
    }

And, of course, you need to change the accessibility of the base class field to protected instead of private. Otherwise, derived classes will not be able to access it.

Of course, this doesn't really save you that much. However, there's no free lunch here. Like I said, this is a limitation of C#, itself, so you have no choice. Although, it's worth mentioning, that while this can sometimes be annoying, it's actually a kind of useful feature of C#. You can look at any class and see exactly what constructors it has available, without having to trace down all its ancestors.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
0

Actually, there is a good solution here:

https://stackoverflow.com/a/48886242/2060975

I am mostly using this method.

[Authorize]
[ApiController]
public abstract class ApiControllerBase : ControllerBase
{
    private IOptions<AppSettings> _appSettings;
    protected IOptions<AppSettings> appSettings => _appSettings ?? (_appSettings = (IOptions<AppSettings>)this.HttpContext.RequestServices.GetService(typeof(IOptions<AppSettings>)));
...
}

I hope it helps someone:)