How to use publish profile to change a value is appsettings.json - asp.net-core

I am using .NET Core 3.0 ASP.net and my appsettings.json looks like this
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"Test":false
}
Is there any way that I could configure a certain publish profile (pubxml) to change the value of Test to either true or false ?

Yes, it's very easy. Currently, you are most likely using the Debug solution configuration for local development. Let's assume you also have Release as solution configuration and want to change certain settings upon publishing to Azure / with your publish profile.
Assuming you are using .NET Core 3.1 (also works with 2.x but the syntax is different), you can this code:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.UseEnvironment(Environment);
});
public static string Environment
{
get
{
string environmentName;
#if DEBUG
environmentName = "development";
#elif RELEASE
environmentName = "production";
#endif
return environmentName;
}
}
Also create a appsettings.product.json where you override specific values.
When you use your publish profile, simply select Release as solution configuration in the publish dialog. That way, you application will load appsettings.json for default values which will be overwritten by values in appsettings.production.json.
You can read more details in the docs.

Related

Set Log Levels for Microsoft.* , System, and AspNet when using Serilog

I had always imagined that
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
would set my project code's log level to Debug, and make Microsoft.* namespaces log at Information level or higher. It seems not. With this config, AspNetCore infrastructure logs at Debug level.
How do I target Microsoft.* to not use the Default level?
I'm using Serilog, but the injected Loggers are all Microsoft.Extensions.Logging.ILogger so I expected Microsoft.Extensions.Logging config to kick in.
Is this a mistaken assumption?
Yes, the assumption that Serilog will respect the Logging.LogLevel section when used with Extensions.Logging is wrong. It doesn't.
To read serilog levels from config, some options are:
use https://github.com/serilog/serilog-settings-configuration and use the config structure they give, especially the section at MinimumLevel, LevelSwitches, overrides
For those who do Serilog config in code, use something like this:
var defaultLogLevel = configuration.GetLogLevel("Default");
var aspNetCoreLogLevel = configuration.GetLogLevel("Microsoft.AspNetCore");
var microsoftLogLevel = configuration.GetLogLevel("Microsoft");
var logger = new LoggerConfiguration()
.MinimumLevel.Is(defaultLogLevel)
.MinimumLevel.Override("Microsoft.AspNetCore", aspNetCoreLogLevel)
.MinimumLevel.Override("Microsoft", microsoftLogLevel)
// ... etc ...
// ...
static LogEventLevel GetLogLevel(this IConfiguration configuration, string #namespace, string fallbackLevel = "Information")
{
return Enum.Parse<LogEventLevel>(configuration["Logging:LogLevel:" + #namespace] ?? fallbackLevel);
}
but the in-config approach for minimum levels has the advantage that you can make use of reloadOnChange

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

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?

Serilog integration in .Net core 2.0 Class Library Project

I would like to use Serilog for logging in .Net core 2.0 class library project. I have searched many places and did not find any example for integrating the Serilog in class library project. Can anybody refer a sample?
Thanks.
You should not set up Serilog logging inside of a class library. A class library is for consumption by other applications, for example an ASP.NET Core web application, or a console application or whatever. The class library is not the entry point of the application, so it should not be responsible for setting up application wide things like logging. It would also be very difficult to do so because a class library does not have a central entry point (by design), so where exactly would you expect to set logging up?
Instead, your library should simply rely on logging to be there and have a way to receive loggers when it needs them. If your application is built with dependency injection in mind, you can just inject your loggers where you need them.
It’s then the responsibility of the application entry point to set up logging and to provide your library with the logging infrastructure.
So if you are using this in an ASP.NET Core context, just follow the guidelines on how to set up Serilog with ASP.NET Core.
You can create a static class logger that is the logging configuration entry point on your class library, like this:
public static Microsoft.Extensions.Hosting.IHostBuilder UseGloabalLogger(this Microsoft.Extensions.Hosting.IHostBuilder app)
{
return app.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration)
.WriteTo.File(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\LOG\\"+string.Format("Logging-{0}.txt",DateTime.Now.ToString("yyyyMMdd")))
.WriteTo.Debug()
.WriteTo.Console(
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}"));
}
then in your Program.cs of webApi o WebApp you must import your class library that reference serilog and initilize them with
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseGloabalLogger()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Best practices wants that any logging configuration must be inserted in your appsettings.json
"Serilog": {
"MinimumLevel": {
"Default": "Information",//or Error or any other
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
..................
}
}

ASP.NET Core ignores ASPNET_ENV and Hosting:Environment

No matter when or where I set either ASPNET_ENV or Hosting:Environment the startup code will always enter
//This method is invoked when ASPNET_ENV is 'Production'
//The allowed values are Development,Staging and Production
public void ConfigureProduction(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(minLevel: LogLevel.Warning);
Configure(app);
}
What I've tried so far
Set Hosting:Environment to Development in the project properties
Set ASPNET_ENV to Development in the project properties
Set Hosting:Environment to Development in launchSettings.json
Set ASPNET_ENV to Development in launchSettings.json
Set ASPNET_ENV to Development in code via Environment.SetEnvironmentVariable("ASPNET_ENV", "Development"); in the Startup method before the call to ConfigurationBuilder.GetEnvironmentVariables()
This is version 1.0.0-rc2-20143 by the way. Am I missing something here or is it just a bug?
The environment variable name has been changed to ASPNETCORE_ENVIRONMENT as part of the name change.
It was announced in this issue and change in this PR.
If you have not done it already, try adding the environment variables to the configuration instance.
public static void Main(string[] args)
{
var builder = new ConfigurationBuilder();
builder.AddJsonFile("appsettings.json");
builder.AddEnvironmentVariables();
var config = builder.Build();
}
Whilst the answer from Henk Mollema is correct for the environment variable name, I still encountered issues where dotnetcore would seem to ignore the environment variable and use appsettings.json when run from command line.
To ensure it uses the correct environment and app settings, try the following:
Change the environment variable via Project Properties -> Debug -> Environment Variables -> ASPNETCORE_ENVIRONMENT -> Value : Change the value to match your intended environment eg Staging
Build Solution
From commandline, type SETX ASPNETCORE_ENVIRONMENT "YOUR-ENVIRONMENT-NAME" where replace "YOUR-ENVIRONMENT-NAME" to match what you set in step 1 eg Staging and ensure you include the "quotes"
IMPORTANT - make sure you all your various appsettings.json eg appsettings.staging.json is present in the project directory where you will run it. (In the case of a published solution, the appsettings.staging.json may not have been copied, so ensure it's there)
From Commandline, go to your project directory (or published directory) and run your project by typing dotnet run (or "dotnet YOURPROJECTNAME.DLL" for published projects)
Observe in the next line that appears in the commandline which states Hosting environment: YOURENVIRONMENTNAME eg Hosting environment:staging
Running a DotNetCore project from Visual Studio always picked the
correct appsettings based on the environment set in your project
properties, however these are the steps I followed to run dotnet core correctly from commandline
working correctly.
This worked for me using .net core 2.0 and building a web api. Notice the 2 different methods of accessing the environment variable.
Program.cs
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args){
if(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT ") == "Production"){
return WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
} else {
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}
But in the startup file there is another environment option
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.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()));
var connectionString = "Data Source=tcp:<some-ip>,<some-port>;Initial Catalog=<some database>;Integrated Security=False;User Id=SA;Password=<some password>;MultipleActiveResultSets=True";
services.AddDbContext<myContext>(opt => opt.UseSqlServer(connectionString));
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors("AllowAll");
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}