ASP.NET Core Configuration

I have seen this common pattern to get connection strings, application configuration settings and logger in ASP.NET core application;

public class HomeController 
{
   private IUnitOfWork _unitOfWork;
   private IConfiguration _configuration;        
   private AppConfig _appConfiguration;
   private readonly ILogger _logger;

   public HomeController(IUnitOfWork unitOfWork, IConfiguration configuration, IOptions<AppConfig> appConfiguration, ILogger<ProjectController> logger)
   {
        _unitOfWork = unitOfWork;
	_configuration = configuration;
        _appConfiguration = appConfiguration.Value;
        _logger = logger;
   }

This works fine but it’s reparative for configurations and logger and violates DRY principal. A good alternative is this;

Register these assemblies in your startup (startup.cs) to take advantage of dependency feature;

public void ConfigureServices(IServiceCollection services)
        {
            //Add functionality to inject IOptions<T>
            services.AddOptions();

            //Add our Config object so it can be injected
            services.Configure<ConnectionString>(Configuration.GetSection("ConnectionStrings"));
            services.Configure<AppConfig>(Configuration.GetSection("AppConfig"));
        }

UPDATE @10/18/2022
For .NET 6, the configuration is;
builder.Services.AddOptions();

builder.Services.Configure<ConnectionString>(builder.Configuration.GetSection("ConnectionStrings"));

builder.Services.Configure<AppConfig>(builder.Configuration.GetSection("AppConfig"));

Create AppConfig POCO class;

public class AppConfig
{
   public string ApplicationName { get; set; }
   public string Version { get; set; }
}

Create a base class and declare these services as properties.

using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

using ConfigDemo.Models;

   public abstract class BaseController<T> : Controller where T : BaseController<T>
    {
        private ILogger<T> _logger;
        private IConfiguration _configuration;
        private IOptions<ConnectionString> _appConnectionString;
        private IOptions<AppConfig> _appConfiguration;

        protected ILogger<T> Logger => _logger ?? (_logger = HttpContext?.RequestServices.GetService<ILogger<T>>());
        protected IConfiguration Configuration => _configuration ?? (_configuration = HttpContext?.RequestServices.GetService<IConfiguration>());
        protected IOptions<ConnectionString> AppConnectionString => _appConnectionString ?? (_appConnectionString = (HttpContext?.RequestServices.GetService<IOptions<ConnectionString>>()));
        protected IOptions<AppConfig> AppConfiguration => _appConfiguration ?? (_appConfiguration = (HttpContext?.RequestServices.GetService<IOptions<AppConfig>>()));

        protected string DisplayMessage
        {
            get { return TempData["DisplayMessage"] == null ? String.Empty : TempData["DisplayMessage"].ToString(); }
            set { TempData["DisplayMessage"] = value; }
        }
    }

We have these values in our appsettings.json file that we would like to use in our application;

{
  "ConnectionStrings": {
    "DBConnection1": "Data Source=(local);Initial Catalog=MyDb1;Persist Security Info=True;Integrated Security=True",
    "DBConnection2": "Data Source=(local);Initial Catalog=MyDb2;Persist Security Info=True;Integrated Security=True"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  //application configratuion here
  "AppConfig": {
    "ApplicationName": "MyApp",
    "Version": "1.0.0"
  }
}

Let’s create a demo view to display output values;

@model String
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Result</title>
</head>
<body>
    <div>
        @Model
    </div>
</body>
</html>

Finally create our first HomeController by inheriting from base controller to read config values;

       public class HomeController : BaseController<HomeController>
    {
        //Navigate to URL, for example https://localhost:44320/home/simpleconfig
        public string Index()
        {
            Logger.LogInformation("I am using dependency injection created in the base cotroller");
            return "Navigate to URL to show an example";
        }

        //using configuration
        public ViewResult SimpleConfig()
        {
            var configValue = Configuration.GetSection("AppConfig").GetChildren();
            string result = configValue.Select(i => i.Value).Aggregate((i, j) => i + "," + j );
            // generate the view
            return View("Result",
            (object)String.Format("Simple Config value: {0}", result));
        }

        //using strong type
        public ViewResult ConfigValueFromConfig()
        {
            string configValue = AppConfiguration.Value.ApplicationName;
            // generate the view
            return View("Result",
            (object)String.Format("App Config value: {0}", configValue));
        }

Run your application and navigate to action method like this;

You can download sample project from GitHub;

https://github.com/shahzy1/ConfigDemoApplication/tree/main

Resources

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0

https://stackoverflow.com/questions/47433027/configuration-getsection-in-asp-net-core-2-0-getting-all-settings

How to run ssis package in asp.net core application?

You can package the assembly into a nuget package, Create a Lib folder inside your solution to hold the nuget package, then, create a nuget.config file to set the package sources to include the Lib folder inside your solution.

The following links contains more details about creating nuget package and hosting it locally:

Alternate Method – 1

To run SSIS package you need below DLLs in the code

  1. Microsoft.SqlServer.ManagedDTS.dll
  2. Microsoft.SqlServer.PipelineHost.dll
  3. Microsoft.SqlServer.DTSRuntimeWrap.dll
  4. Microsoft.SqlServer.DTSPipelineWrap.dll

It is easy to add DLLs in MVC projects, however in asp.net core it needs to be in form of a Nuget package.

So nuget package can be easily created using nuget package explorer. Below is the link

https://docs.nuget.org/create/using-a-gui-to-build-packages

In the nuget package explorer add a lib folder, inside that add a .net folder dnxcore50 and add the above DLLs. Click on tools analyse package and save the nuget.

In the visual studio 2015 solution, you can refer local packages. Tools – Nuget Package Manager – Package Manager Settings – Package source add the local package path.

After which you will be able to add the nuget package using nuget package manager and select local package as source

"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final",
"Microsoft.NETCore.Portable.Compatibility": "1.0.1-rc2-24027",
"SSISPackage": "1.0.0"
 }

"frameworks": {
"netcoreapp1.0": {
  "imports": [
    "dotnet5.6",
    "portable-net45+win8",
    "dnxcore"
  ]
  }
}

After which you will be able to use code to run SSIS package similar to MVC projects.

Application app = new Application();
        Package package = null;
        try
        {
            package = app.LoadPackage(@"C:\Files\Package.dtsx", null);
            Variables vars = package.Variables;
            vars["status"].Value = "ACTIVE";

            DTSExecResult results = package.Execute();

        }
        catch
        {
            return false;

        }
        finally
        {
            package.Dispose();
            package = null;
        }

Alternate Method – 2

You may now reference the dlls ( one from each) directly in your .net core project from the below locations to run ssis packages now

C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.ManagedDTS
C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.PipelineHost
C:\Windows\Microsoft.NET\assembly\GAC_64\Microsoft.SqlServer.DTSRuntimeWrap
C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.DTSPipelineWrap

you no longer need to create a nuget package

Reference

https://stackoverflow.com/questions/38791987/how-to-run-ssis-package-in-asp-net-core-application

Entity Framework Core tools reference .NET Core CLI

The command-line interface (CLI) tools for Entity Framework Core perform design-time development tasks. For example, they create migrations, apply migrations, and generate code for a model based on an existing database.

dotnet ef can be installed as either a global or local tool. Most developers prefer installing dotnet ef as a global tool using the following command:

dotnet tool install –global dotnet-ef

Update the tool tool using the following command:

dotnet tool update –global dotnet-ef

Before you can use the tools on a specific project, you’ll need to add the Microsoft.EntityFrameworkCore.Design package to it.

dotnet add package Microsoft.EntityFrameworkCore.Design

Verify installation

dotnet ef

The output from the command identifies the version of the tools in use:

For further details, refer to this link;

https://docs.microsoft.com/en-us/ef/core/cli/dotnet