ASP .Net Core 2.0 - Reading appsettings.json from a non-parameterized class

0

I'm starting with an asp.net core 2.0 mvc web and I can not read directly from a class the value of the appsettings.json (ConnectionString) that I need.

I've found a lot of documentation, although none of them gets what I want. Summing up all the documentation that I have read, what the majority proposes is the following:

  • Create an "appSettings" class
  • Add a new service in Setup.cs (ConfigureServices)
  • Inject the values into the controller's constructor and access the data from there.
  • One of the many examples I found: link

    The problem I have is that I am structuring the code in three layers (interface, business logic and data access) that call each other respectively and I do not see how to get to the access layer. data the connection string without having to send it by parameter through the different layers.

    Right now the idea that I have in my head is to be able to read from the data access class the values of the appsettings.json, although if someone knows another better way to do it I would also like to know.

    Thanks in advance.

    Edit1:

    AppSettings.cs

    Class that I created to store appsettings.json data

    public class AppSettings
    {
        public Connection Connection { get; set; }
    }
    
    public class Connection
    {
        public string ConnectionString { get; set; }
    }
    

    Startup.cs

    I understand that here the "AppSettings" class is added to the service container.

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    
    public IConfiguration Configuration { get; }
    
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    
        services.AddOptions();
    
        // Add appSettings
        services.Configure<AppSettings>(settings =>
        {
            settings.Connection = new Connection()
            {
                ConnectionString = Configuration["Data:DefaultConnection:ConnectionString"]
            };
        });
    
        services.AddSingleton<IConfiguration>(Configuration);
    }
    

    DataAccess.cs

    Data access layer. Where I should be able to access AppSettings.

    private readonly AppSettings _settings;
    
    public DataAccess(IOptions<AppSettings> settings)
    {
        _settings = settings.Value;
    }
    

    BusinessLogic.cs

    Business layer, where I instantiate the data access layer. It generates a compilation error because there are missing parameters to send to the constructor, which seems logical to me. Maybe I can not understand the injection of dependencies very well.

    public Business()
    {
        Data = new DataAccess();
    }
    

    Edit2: This is how I have solved it, in case someone is good for something

    Startup.cs

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services
            services.AddMvc();
    
            // Configure AppSettings
            services.Configure<AppSettings>(settings =>
            {
                settings.Data = new Data()
                {
                    ConnectionString = Configuration["Data:ConnectionString"].ToString()
                };
            });
    
            // Configure BusinessLogic
            services.AddSingleton<IBusinessLogic, BusinessLogic>();
            // Configure DataAccess
            services.AddSingleton<IDataAccess, DataAccess>();
        }
    
         public void Configure(IApplicationBuilder app, IHostingEnvironment env) ...
    }
    

    DataAccess.cs

    public class DataAccess : IDataAccess
    {
        private readonly AppSettings _settings;
    
        public DataAccess(IOptions<AppSettings> settings)
        {
            _settings = settings.Value;
        }
    
        public string GetConnectionString()
        {
            return _settings.Data.ConnectionString;
        }
    }
    
      

    In the data access layer I create a test method that returns the   connection string.

    BusinessLogic.cs

    public class BusinessLogic : IBusinessLogic
    {
        private readonly IDataAccess _data;
    
        public BusinessLogic(IDataAccess data)
        {
            _data = data;
        }
    
        public string GetConnectionString()
        {
            return _data.GetConnectionString();
        }
    }
    
      

    In the business layer I create another test method that returns the   connection string. This in turn gets it from the data layer.

    HomeController.cs

    public class HomeController : Controller
    {
        private readonly IBusinessLogic _businness;
    
        public HomeController(IBusinessLogic business)
        {
            _businness = business;
        }
    
        public IActionResult Index()
        {
            return View(new HomeModel(_businness.GetConnectionString()));
        }
    }
    
      

    In the Home view controller, I paint the chain of   connection obtained from the business layer.

        
    asked by zeross 27.03.2018 в 22:28
    source

    3 answers

    2

    If you define the appSettings class in a separate project that you can reference from the data access layer and the web, then you could inject the'IOptions < > 'into the class constructor

    Options pattern in ASP.NET Core

    It is clear that the data access class must resolve by dependency injection, so that the IOptions applies

    public class xxDataAccess : IxxDataAccess {
    
        private readonly AppSettings settings;
    
        public xxDataAccess(IOptions<AppSettings> settings){
    
            this.settings = settings.Value;
    
        }
    
        //resto codigo
    
    }
    

    Based on your example, it would be

    public class DataAccess : IDataAccess {
    
       private readonly AppSettings _settings;
    
       public DataAccess(IOptions<AppSettings> settings)
       {
           _settings = settings.Value;
       }
    }
    
    
    public class Business: IBusiness {
    
       private readonly IDataAccess data;
    
       public Business(IDataAccess data)
       {
           this.data = data;
       }
    }
    

    remember to define the Business in the controller constructor and all this in the asp.net core config injection

        
    answered by 28.03.2018 / 05:21
    source
    2

    In Startup, when you configure your connection, you can do it this way:

    Configuration.GetConnectionString("nombre_de_conexion");
    

    As you mention Business Layer I can believe that you use some DBContext for access to the database, if so, in Startup you can find the following method:

    public void ConfigureServices(IServiceCollection services)
    {
        //aquí puedes poner algo como esto:
        services.AddDbContext<TuDBContext>(options =>      
        options.UseSqlServer(
        Configuration.GetConnectionString("nombre_de_conexion")));
    }
    

    PD: options.UseSqlServer can change depending on what you use for database, it can be UseSqlite or UseMysql.

        
    answered by 03.04.2018 в 19:43
    2

    You can get the connection string from anywhere in the project, rebuilding IConfiguration from the file "appsetting.json" knowing the location with "Directory.GetCurrentDirectory ()" if you are in the same project or assigning the path where you are the appsetting.json.

    public static IConfiguration Configuration { get; set; }
    
    private string GetConnectionString()
    {
        var builder = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json");
    
        Configuration = builder.Build();
    
        return Configuration.GetConnectionString("DefaultConnection");
    
    }
    

    Remember to have the following structure in the appsetting.json file:

    {
      "Logging": {
        "IncludeScopes": false,
        "Debug": {
          "LogLevel": {
            "Default": "Warning"
          }
        },
        "Console": {
          "LogLevel": {
            "Default": "Warning"
          }
        }
      },
      "ConnectionStrings": {
        "DefaultConnection": "Server=((local));Database=database;Trusted_Connection=True;user id=xx;password=xxxx;"
      }
    }
    
        
    answered by 20.04.2018 в 20:53