Configure logging via config file in .NET Core - asp.net-core

We are trying to configure logging for our ASP.NET Core application via a configuration file (the default appsettings.json). The docu says it should be possible (https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1), but we can't get it working like expected.
What we have tried so far:
leave the code as it is in the project template for ASP.NET Core and just change the appsettings.json => no effect
explicitly add appsettings.json as config file and configure logging in Program.cs => no logging at all
public static IHostBuilder CreateHostBuilder (string[] args) =>
Host.CreateDefaultBuilder (args)
.ConfigureAppConfiguration ((hostingContext, config) =>
{
config.Sources.Clear ();
var env = hostingContext.HostingEnvironment;
config.AddJsonFile ("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile ($"appsettings.{env.EnvironmentName}.json",
optional: true, reloadOnChange: true);
config.AddEnvironmentVariables ();
})
.ConfigureLogging ((hostingContext, logging) =>
{
logging.ClearProviders ();
logging.AddConfiguration (hostingContext.Configuration.GetSection ("Logging"));
})
.ConfigureWebHostDefaults (webBuilder =>
{
webBuilder.UseStartup<Startup> ();
});
... configure logging in Startup.ConfigureServices => no effect
public void ConfigureServices (IServiceCollection services)
{
services.AddLogging (config => config.AddConfiguration (Configuration.GetSection("Logging")));
services.AddControllers ();
}

You misunderstood. You can configure logging, i.e. log levels for each provider, filtering out messages, etc., but the actual providers must be assigned in code. In other words, you can configure what messages go to the console via config, but you must still call logging.AddConsole() within ConfigureLogging to add that provider.
The code you have clears all the default providers and adds nothing, so there's no providers at all and hence no logs are generated. You cannot actually add the providers via config, just configure providers that have been added.

Related

Adding AWS.Logging.NLog to existing loggers in .Net Core 6 when building the host

I have an existing "Logging" section on my appsettings.json that writes to a rolling local file. But I'd like to add AWS logging as well.
I am used to code like this to add another NLog target, but I haven't a clue how to do this with AWS.Logging.NLog
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.UseSystemd()
.ConfigureAppConfiguration((w, c) =>
{
c.AddCustomJsonFile("app.config.json", optional: true, reloadOnChange: true);
// allow for custom overrides for this specific config (this is handled already for appsettings.json)
if (w.HostingEnvironment.EnvironmentName != Environments.Production)
{
c.AddCustomJsonFile($"app.config.{w.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true);
}
}).ConfigureLogging((hostContext, logBuilder) =>
{
// REMOVE THIS CODE BELOW AND ADD AWS Logging...
//
// If we are configured to additionally use NLog, added it to the logging configuration
//
if (hostContext.Configuration.GetSection("Logging:NLog").Exists()) {
logBuilder.AddNLog(
new NLogLoggingConfiguration(
hostContext.Configuration.GetSection("Logging:NLog")
)
).SetMinimumLevel(LogLevel.Information);
}
NEWEST
Add AWS.Logger.SeriLog NuGet package in your project.
For more details, please check this blog.
How To Write Logs To Amazon CloudWatch Using Serilog In .NET 6 Web API
PREVIOUS
It seems you still use the previous structre in .net 6 project.
Adding Amazon CloudWatch as a logging provider is easily done by calling the AddAWSProvider extension method of the ILoggingBuilder as shown below.
Using .NET Logging Providers

Migration to Minimal API - Test Settings Json not overriding Program

Thanks to this answer: Integration test and hosting ASP.NET Core 6.0 without Startup class
I have been able to perform integration tests with API.
WebApplicationFactory<Program>? app = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
});
});
HttpClient? client = app.CreateClient();
This has worked using the appsettings.json from the API project. Am now trying to use integrationtestsettings.json instead using:
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(ProjectDirectoryLocator.GetProjectDirectory())
.AddJsonFile("integrationtestsettings.json")
.Build();
WebApplicationFactory<Program>? app = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureAppConfiguration(cfg => cfg.AddConfiguration(configuration));
builder.ConfigureServices(services =>
{
});
});
_httpClient = app.CreateClient();
I have inspected the configuration variable and can see the properties loaded from my integrartiontestsettings.json file. However, the host is still running using the appsettings.json from the server project.
Previously, in .Net5, I was using WebHostBuilder and the settings were overridden by test settings.
WebHostBuilder webHostBuilder = new();
webHostBuilder.UseStartup<Startup>();
webHostBuilder.ConfigureAppConfiguration(cfg => cfg.AddConfiguration(_configuration));
But cannot get the test settings to apply using the WebApplicationFactory.
It seems the method has changed.
Changing:
builder.ConfigureAppConfiguration(cfg => cfg.AddConfiguration(configuration));
To:
builder.UseConfiguraton(configuration);
has done the trick.
builder.ConfigureAppConfiguration, now it's configuring the app (after your WebApplicationBuilder.Build() is called) and your WebApplication is created.
You need to "inject" your configurations before the .Build() is done. This is why you need to call UseConfiguraton instead of ConfigureAppConfiguration.

Asp.Net Core cookie authentication options login path is routed via HTTP

The below portion of my startup.cs shows that I am using cookies based authentication. The option for "LoginPath" is utilized when an unauthenticated user tries to hit a resource that is protected. The problem is that this is done via HTTP. I want the resultant response/redirect to the login page to be HTTPS.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/login";
....
I tried to hard code the LoginPath so that it would be forced to go through an HTTPS path, but I found that that option must be a relative path.
There is a downstream process (server/load balancer/something) which I have no power or viewership of that does a redirect to HTTPS, but this is not before the HTTP response occurs. I don't want that downstream process to have to handle the HTTP request. I would prefer this were handled in the application.
I had previously looked at and glossed over the following answer, but it appears to work for my needs: ASP.NET Core CookieAuthenticationOptions.LoginPath on different domain
My final, modified (several options removed) solution within configure services in startup.cs:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Login";
options.Events = new CookieAuthenticationEvents()
{
OnRedirectToLogin = (context) =>
{
context.HttpContext.Response.Redirect(context.RedirectUri.Replace("http://", "https://"));
return Task.CompletedTask;
}
};
});
You would need to add a using to startup.cs for System.Threading.Tasks if you don't already have it.

Is there a way to deactivate IIS integration in Net Core 3.X app without having to reproduce the code from CreateDefaultBuilder

In version 3.0 and up of Net Core a web application can be setup this way:
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureAppConfiguration(config =>
{
var settingsFile = Environment.GetEnvironmentVariable("APP_SETTINGS");
if (!string.IsNullOrWhiteSpace(settingsFile))
{
config.AddJsonFile(settingsFile, optional: false);
}
});
webBuilder.UseStartup<Startup>();
});
While using CreateDefaultBuilder very convenient and abstracts a lot of boilerplate, it also forcibly enables IIS integrations for the app. In my case, I want to run the app using raw Kestrel without IIS proxying requests.
Is my only choice to extract all the boilerplate from CreateDefaultBuilder() if I want to not use the IIS integrations, or can I somehow overwrite this? I've been studying the source code for this methods and I can't see a way to solve this.
Do you know of an easier method to achieve this other than having to write all the setup code myself?

ASP.NET Core 2: In `Startup()`, how do I specify additional arguments to choose the right configuration?

We are building a new ASP.NET Core app to deploy to a few different environments that require different Configuration options. For example, Azure, AWS, and local for development. Each needs different configuration settings. We already use the common:
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
which handles debug vs staging vs prod, but we have a second dimension to it, so we also want a:
.AddJsonFile($"appsettings.{DeploySite}.json", optional: true)
or something like that. We could pass in the DeploySite on commandline or environment variable or whatever is convenient, but nothing like that seems exposed in the IHostingEnvironment offered in the Startup method.
How is this best accomplished?
In ASP.NET Core 2+ this is done in Program.CreateWebHostBuilder instead of Startup. We do something almost identical in our deployments, requiring an appsettings.<name>.json file for configurations. We do it by passing in a command line parameter in the form of --App:InstanceName <name>. Then set it on launch:
public static void Main(string[] args)
{
IWebHost host = CreateWebHostBuilder(args).Build();
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureAppConfiguration((hostContext, config) =>
{
IConfigurationRoot commandConfig = config.Build();
config.AddJsonFile($"appsettings.{commandConfig["App:InstanceName"]}.json", optional: true, reloadOnChange: true);
});
}