Using custom configuration provider for Serilog - asp.net-core

I have a ASP.NET Core 3.1 Web API application in which I am using Serilog with Serilog.Sinks.MSSqlServer sink.
Questions:
Is it possible to read Serilog's MSSQL sink configuration (E.g. connection string) using some custom configuration provider if it's not possible to configure settings in the appsettings file?
Is it possible to do some settings on LoggerConfiguration at the end AFTER all the required dependencies are registered? (Something like what we do using IPostConfigureOptions.)
High level description of the problem if you want to know what I am up to:
In my organization, all application settings are stored in a common database. What it means is that the ConnectionString I need for the Serilog MSSqlServer sink will also be in the common database.
Serilog is configured at the Host level using IHostBuilder in Program.cs. On the other hand, the services which read settings from our common database are registered in ASP.NET Core's DI in Startup.cs.
I added a class named SerilogPostConfigure which implements IPostConfigureOptions<LoggerConfiguration> and registered it in Startup.cs like this services.ConfigureOptions<SerilogPostConfigure>(). In this class, I inject all the dependencies which can help me connect to the common database to get the required connection string. However, this class is never invoked ! I don't understand why.

I think you should try to use a custom configuration provider on ASP.NET Core level. You can tell the ASP.NET Core app to read the application's configuration from custom places (It reads from your appsettings.json file and environment variables by default).
Here is an article about creating a custom config provider, that reads configuration from a database: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#custom-configuration-provider

Related

asp.net core populate environment variables from appsettings.json

I have a solution layed out as follows -
Class library
Azure Function
.net Core Web App
The class library is shared between the function and web app and obtains configuration values by calling Environment.GetEnvironmentVariable(). This works great for the Azure function, I can specify the values in local.settings.json for development and in Configuration -> application settings in the azure portal.
In the web app I am building the configuration like so -
builder.Configuration
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile($"appsettings.json", true, true)
.AddEnvironmentVariables();
Then I am injecting IConfiguration config into the controller's constructor but I would like the functionality to work the same as the Azure Function, so that in the class library, Environment.GetEnvironmentVariable() will return the values from appsettings.json in the web app .
Question - how can I get the web app to populate environment variables in the same way Azure Functions do?

Does Service Principal (SPN) values has to be change while doing ADAL.Net to MSAL.Net migration?

We have a Web Application in .Net Core 6.0 that we have registered in Azure AD app registration in azure portal.
We have used ADAL.net library in our code for Authentication. Now, we are migrating authentication library Adal.net to Msal.Net.
We have used below endpoints URLs to generate tokens
https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize
https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token
When we migrate the application, we have to change the library references and related code in our application.
We want to confirm on the below points -
Do we need do any changes in app registration configuration in azure portal or any code level configuration changes in application related to MSAL.Net Library like in appsettings or startup.cs class?
Do we need to do any change in service principal (SPN) values?
If you are on ASP.NET Core 6.0, you should use Microsoft.Identity.Web, which provides higher-level APIs on top of MSAL.NET. See the migration guide here. You do not need to change any of your app registration when migrating, include the service principal values.

Machine key implementation in .NET Core 3.1

In ASP.NET we would normally add a machine key to the web.config like this -
<machineKey validation="HMACSHA512" decryption="AES" validationKey="********" decryptionKey="******" />
Can someone please advises me how can we do the same in ASP.NET Core 3.1?
To enable SSO (Single Sign On) for multiple web applications on your site make sure that in the Startup.cs of all your web applications you add DataProtection and set the same ApplicationName, save the keys to the same directory and use the same cookie name like this:
services
.AddDataProtection()
.SetApplicationName("MyWebSite")
.PersistKeysToFileSystem(new DirectoryInfo(#"C:\MyWebSite-keys"));
services
.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
options =>
{
options.LoginPath = "/login/login";
options.Cookie.Path = "/";
options.Cookie.Name = "MyWebSite-Login";
});
machineKey is no longer used in Core, instead of validationKey and decryptionKey only the masterkey will be used and will be created automatically in the directory you specify.
After this, after logging in application A and requesting application B the user will remain logged in.
You will need the install this package: Microsoft.AspNetCore.DataProtection.SystemWeb
It neeeds to be ASP.NET 4.5.1+.
Read more here: Replace the ASP.NET machineKey in ASP.NET Core
In Asp.net Core Application, you can implementation the <machineKey> element using the Data Protection API.
To use the Data Protection API in asp.net core application, first, install the package Microsoft.AspNetCore.DataProtection.SystemWeb. You might meet a warning "Warning NU1701...This package may not be fully compatible with your project.", on my side, this warning will not influence us to use this package.
[Note] The new data protection system can only be installed into an existing ASP.NET application targeting .NET 4.5.1 or later. Installation will fail if the application targets .NET 4.5 or lower.
Then, register the Data Protection service in the Startup.cs file, like this:
services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(#"D:\temp\temp-keys\"));
After running the application, the generate file content as below:
The above code was configured a file system-based key repository to store the machine key, you can also use Azure Storage, Redis, Registry or Entity Framework Core. More detail information, check the Key storage providers in ASP.NET Core

What is the difference between IWebHost WebHostBuilder BuildWebHost

After reading Microsoft documents I am still confused. I need to deploy a .net core 2 web application I developed to an IIS server and I can't get a straight forward answer on anything. This is just the beginning of my questions.
What is the difference between IWebHost, WebHostBuilder, BuildWebHost?
Thanks!
First of all, let me start with that I very much disagree with your statement: The documentation on ASP.NET Core is actually very good. Yes, it may be still lacking in some details, and it also has some problems catching up to changes with releases, but overall the content is really good and the team working on it is really doing a remarkable job. It’s really difficult to author a documentation for such a large and fast-moving framework, and the amount of information you get through the documentation is actually very good. You will likely get to recognize that once you have overcome the initial problems in starting with a new framework.
But coming back to your question:
IWebHost: The web host is the general thing that hosts and runs your web application. It gets created when your application starts up, and then it will construct all the necessary pieces, like the Kestrel web server, the application middleware pipeline, and all the other bits, and connects them, so that your application is ready to serve your requests.
The web host is basically the thing that makes up your web application.
IWebHostBuilder: The web host builder is basically a factory to create a web host. It is the thing that constructs the web host but also configures all the necessay bits the web host needs to determine how to run the web application.
With ASP.NET Core 2, you will usually create a “default web host builder” which will already come with a lot defaults. For example, the default web host will set up the Kestrel web server, enable and configure logging, and add support for the appsettings.json configuration.
Usually, your applications will always start with such a default web host and you then just use the web host builder to subsequently configure the web host before it is actually being built.
BuildWebHost is part of the older convention before ASP.NET Core 2.1 where the default pattern in the Program.cs was to build the web host in a separate method. With 2.1, this was changed so that the method would no longer build the web host directly but just create the web host builder (hence the method now being called CreateWebHostBuilder). So basically, the .Build() call on the web host builder was refactored out of the method. You can see this nicely in the migration guide for 2.0 to 2.1.
The reason this was done is to make the CreateWebHostBuilder reuseable. The builder configuration that happens in that method is basically everything that is necessary to configure the web host. So by making that reusable, without generating an actually created web host, it can be used for other purposes. In this case, this was done for integration testing using the TestHost. The test host will basically host the web host internally for your integration tests, and it will do so by looking for the CreateWebHostBuilder method.
With ASP.NET Core 2.1, the default pattern you see in the Program.cs is the following (comments added by me for further explanations):
public class Program
{
// main entry point for your application
public static void Main(string[] args)
{
// create the web host builder
CreateWebHostBuilder(args)
// build the web host
.Build()
// and run the web host, i.e. your web application
.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
// create a default web host builder, with the default settings and configuration
WebHost.CreateDefaultBuilder(args)
// configure it to use your `Startup` class
.UseStartup<Startup>();
}
Btw. this topic is generally covered in the application startup and hosting sections of the official documentation.
ASP.NET Core 3.x
Starting with ASP.NET Core 3.0, there has been a change with the setup I described above. The reason for this is the generic host. The “generic host” is a generalization of the web host and the web host builder, to allow non-web scenarios outside of ASP.NET Core, making ASP.NET Core itself just a “hosted service” that runs on top of the generic host.
IHost: The host is the component that hosts and runs your application and its services. This is a generalization of the previous IWebHost but fullfills basically the same task: It starts configured hosted services and makes sure that your app is running and working.
IHostBuilder: The host builder constructs the host and configures various services. This is the generalization of the previous IWebHostBuilder but also basically does the same just for generic IHost. It configures the host before the application starts.
There is the Host.CreateDefaultBuilder method that will set up a host with various defaults, e.g. configuration using appsettings.json and logging.
IHostedService: A hosted service is a central component that the host hosts. The most common example would be the ASP.NET Core server, which is implemented as a hosted service on top of the generic host.
You can also write your own hosted services, or add third-party services that allow you to nicely add things to your application.
The generic host introduced with ASP.NET Core 3.0 and .NET Core 3.0 basically replaces the previous IWebHost and IWebHostBuilder. It follows the very same architecture and idea but is simply reduced to non-web tasks so that it can work with a number of different purposes. ASP.NET Core then just builds on top of this generic host.

Read configuration from a specific file - Web.config or appsettings.json based on the calling web application

I have a monolith project and I'm trying to convert one Web Application from ASP.NET to ASP.NET Core with Full Framework.
As you can see from the figure, both Web Applications are referencing Class Library 3. CL3 contains Business Logic but also logic about how to read specific configuration (till now from Web.config file).
Since the way to read configuration has changed in ASP.NET Core (appsettings.json Environment based) I have to rewrite the part that reads the configuration from CL3.
Is it possible a scenario like this?
#IF CALLED FROM ASP.NET
RETRIEVE CONFIGURATION FROM WEB.CONFIG
#ELSE (CALLED FROM ASP.NET CORE FULL FRAMEWORK)
RETRIEVE CONFIGURATION FROM APPSETTINGS.JSON
If you are refactoring, try to move configuration reads out of the shared DLLs and provide a clean abstraction that does not have hidden dependencies on framework-specific assets.
Your ASP.NET Core Application and classic ASP.NET Applications could create a config based on their config system (you could provide two different config implementations) and then use your CL3's classes and pass in configuration objects.
Alternatively, you could use a ConfigurationBuilder to read AppSettings and connection strings from appsettings.json and appsettings.{Environment}.json and make it available through the classic ConfigurationManager API. See this blog post for details on how to do this. This can be extended to configuring custom configuration sections (classic .NET) from json files.