How to configure .NET Core logging json file to ignore certain events? - asp.net-core

I would like to ignore certain warnings in prod system. The code equivalent I was given is this:
optionsBuilder
.ConfigureWarnings(x => x.Ignore(RelationalEventId.MultipleCollectionIncludeWarning));
Is it possible to set the ignore in appSettings.Production.json instead?
Currently it is:
"Logging": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.EntityFrameworkCore": "Warning",
"IdentityServer4": "Information"
}
},

I'm not an EF Core expert, but it seems evident these are two different types of configuration; the builder call is telling EF Core what events to log or not, and the appsettings is just instructing the logging framework which providers to listen to at which levels. You might be able to mute the entire provider at a given log level, but that would likely not be granular enough to filter just a certain class of log events within that provider.
If EF Core does not have a native mechanism for reading in an Options class from a Configuration object and you have a limited set of switches you'd want to manage (i.e. just a single group of things that may be turned on or off together), then you can write your own to help manage it.
Configuration class:
public class CustomEfCoreLoggingOptions
{
public const string Section = "CustomEfCoreLogging";
public bool IgnoreMultipleCollectionIncludeWarning { get; set; }
}
Appsettings:
"CustomEfCoreLogging" : {
"IgnoreMultipleCollectionIncludeWarning" : true
}
In your startup:
var efLogging = Configuration.GetSection(CustomEfCoreLoggingOptions.Section).Get<CustomEfCoreLoggingOptions>();
var optionsBuilder = new DbContextOptionsBuilder();
if (efLogging.IgnoreMultipleCollectionIncludeWarning) optionsBuilder.ConfigureWarnings(x => x.Ignore(RelationalEventId.MultipleCollectionIncludeWarning));
//...

Related

Not able to configure connection string in ASP.net MVC Core 5.0 & Entity Framework Core application

I'm getting below error when I configure SQL Connection in ASP.Net Core MVC 5 and Entity Framework core.
I've configured in Startup.cs file:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<VMSDBContext>(
options => options.UseSqlServer(Configuration.GetConnectionString("VMSDatabase"))
);
}
My appsettings.json file:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"ConnectionStrings": {
"VMSDatabase": "Server=.;Database=VMS;Trusted_Connection=True;"
},
"AllowedHosts": "*"
}
InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the 'DbContext.OnConfiguring' method or by using 'AddDbContext' on the application service provider. If 'AddDbContext' is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.
You're looking for a connection called "VMSDatabase" in your code. But you've configured a connection called "AgileOneVMSDatabase" in your appsettings. Change either one of them so to the same and this should solve your issue.
According to your description, I guess the reason why you faced this issue is you used the wrong VMSDBContext's constructor method. If this class's
constructor method doesn't contains the DbContextOptions parameter, it will face this error.
I suggest you could change it like below:
public VMSDBContext(DbContextOptions options) : base(options) {}

InstrumentationKey not picked up when stored in key vault

I am using a key-vault to store all the keys used in my bot v4 solution. I suspect the InstrumentationKey is not picked up correctly. What should be the name of the ApplicationInsights- InstrumentationKey in the key-vault.
In appsetting.json the key is added like this :
"ApplicationInsights": {
"InstrumentationKey": "xxxx-xxxx-xxx-xxxx-xxx" }.
I had the same issue. These were the steps I followed to resolve it in an ASP.NET Core MVC 5 application:
In Program.cs file, the code for adding configuration values from Key Vault in Production environment (based on https://learn.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?view=aspnetcore-5.0#use-managed-identities-for-azure-resources):
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
if (context.HostingEnvironment.IsProduction())
{
var builtConfig = config.Build();
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
config.AddAzureKeyVault(
$"https://{builtConfig["KeyVaultName"]}.vault.azure.net/",
keyVaultClient,
new DefaultKeyVaultSecretManager());
}
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
In Azure Key Vault create a new secret with the name "ApplicationInsights--InstrumentationKey" and give it the value of the production application insights instrumentation key. In order for your app service to be able to communicate with the key vault and read the secrets, you need to firstly enable the system assigned service identity for your azure app service and then create a key vault Access Policy for Get, List operations for secrets and assign the policy to the previously created system assigned service identity.
In appSettings.Production.json file:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"KeyVaultName": "{your-keyvault-name}",
"ApplicationInsights": {
"CloudRoleName": "TinyCrm.Web.Prod",
"DisableTelemetry": false,
"EnableAdaptiveSampling": true
}
}
To register the application insights specific stuff for the aspnet core DI framework I created the following extension method. I am using Microsoft.ApplicationInsights.AspnetCore version 2.17.0 nuget package. (taking into consideration what is written here https://learn.microsoft.com/en-us/azure/azure-monitor/app/asp-net-core#user-secrets-and-other-configuration-providers):
public static IServiceCollection AddApplicationInsights(this IServiceCollection services, IConfiguration configuration)
{
// Register the settings for "ApplicationInsights" section as a service for injection from DI container
var applicationInsightsSettings = new ApplicationInsightsSettings();
configuration.Bind(ApplicationInsightsSettings.ApplicationInsightsSectionKey, applicationInsightsSettings);
services.AddSingleton(applicationInsightsSettings);
// Use telemetry initializers when you want to enrich telemetry with additional information
services.AddSingleton<ITelemetryInitializer, CloudRoleTelemetryInitializer>();
// Remove a specific built-in telemetry initializer
var telemetryInitializerToRemove = services.FirstOrDefault<ServiceDescriptor>
(t => t.ImplementationType == typeof(AspNetCoreEnvironmentTelemetryInitializer));
if (telemetryInitializerToRemove != null)
{
services.Remove(telemetryInitializerToRemove);
}
// You can add custom telemetry processors to TelemetryConfiguration by using the extension method AddApplicationInsightsTelemetryProcessor on IServiceCollection.
// You use telemetry processors in advanced filtering scenarios
services.AddApplicationInsightsTelemetryProcessor<StaticWebAssetsTelemetryProcessor>();
// The following line enables Application Insights telemetry collection.
services.AddApplicationInsightsTelemetry();
return services;
}
In Startup.cs file:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// Call the extension method we created above
services.AddApplicationInsights(Configuration);
}
Important note: Make sure when you create the new Azure App Service to not enable the Application Insights Telemetry integration automatically from the Azure app service creation wizard (see below image). Instead create the application insights resource yourself and setup your app to use the instrumentation key in production environment through following the above steps.
Azure App Service Creation Wizard

DbContext class in .Net Core

Hi Guys I am trying to migrate from Asp.Net MVC 5 to .Net Core 2.0 Web Application.
I am stuck with a error saying :
Cannot convert from 'string' to
'Microsoft.EntityFrameworkCore.DbContextOptions'
I get the above error when I hover over the class:
public class ExampleModelWrapper : DbContext
{
public ExampleModelWrapper()
: base("name=EXAMPLE_MODEL")
{
}
}
ExampleModelWrapper is a model.
I referred to the following question in stack overflow:
How can I implement DbContext Connection String in .NET Core?
I have the connection string in appsettings.json:
{
"ConnectionStrings": {
"EXAMPLE_MODEL": "Server=(localdb)\\mssqllocaldb;Database=aspnet-Monitoring-CCA7D047-80AC-4E36-BAEA-3653D07D245A;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}
I have provided the service in startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("EXAMPLE_MODEL")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
services.AddMvc();
}
What can be the reason for the above error. I believe a connection is being established to the database successfully ,as it is working for the login and registration flow of Identity Db.I am also stumped on how or where to change the connections for the identity Db. Help appreciated , Thank you!!
You need to use the following constructor in your DbContext
public ExampleModelWrapper (DbContextOptions<ExampleModelWrapper> options)
: base(options)
{
}
Within your startup, you need to modify the following:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("EXAMPLE_MODEL")));
to the following:
services.AddDbContext<ExampleModelWrapper>(options =>
options.UseSqlServer(Configuration.GetConnectionString("EXAMPLE_MODEL")));
Basically, you need to specify the DbContext you need to use.

.NET Core 2, DI, configuration file

I am studying .NET Core 2 and I don't like how DI is managed... on the web I read something like the following steps:
creating an interface like IService
creating an implementation for IService
adding it on the scope of .NET Core container into Startup.Configuration method resolving the dependency.
finally I can use it into the constructor of my custom controller.
In .NET classic I used a dedicated XML configuration file to manage dependencies: can I use a configuration file (JSON or XML are the same) to do the same I would have to do into Startup.Configuration method?
...otherwise someone can explain me the reason why configure the services into Startup.Configuration is the better way?
Thanks so much...
First, to answer your question "can I use a configuration file", the answer is emphatically "yes". Why shouldn't you is answered later, but for now, here's a poor man's version of how you might do this by adding to your appsettings.json file. Note that this code is not optimal, but is designed to show you how you could implement this solution.
Let's start with some classes to hold the data:
public class ServicesConfiguration
{
public IEnumerable<ServiceItem> Singleton { get; set; }
public IEnumerable<ServiceItem> Transient { get; set; }
}
public class ServiceItem
{
public string Service { get; set; }
public string Implementation { get; set; }
}
Now add a section to your JSON file, you may even want to keep this file external to the main config, but that's an implementation detail I will leave up to you:
{
//snip main config....
"Services" : {
"Singleton": [
{
"Service": "YourNamespace.IFoo1, YourNamespace",
"Implementation": "YourNamespace.Foo1, YourNamespace"
},
{
"Service": "YourNamespace.IFoo2, YourNamespace",
"Implementation": "YourNamespace.Foo2, YourNamespace"
}
],
"Transient": [
{
"Service": "YourNamespace.IBar1, YourNamespace",
"Implementation": "YourNamespace.Bar1, YourNamespace"
}
]
}
}
And now an extension method to configure it all:
public static IServiceCollection AddFromConfigurationFile(this IServiceCollection services,
IConfigurationSection configuration)
{
var servicesConfiguration = configuration.Get<ServicesConfiguration>();
foreach(var service in servicesConfiguration.Singleton)
{
services.AddSingleton(Type.GetType(service.Service), Type.GetType(service.Implementation));
}
foreach(var service in servicesConfiguration.Transient)
{
services.AddTransient(Type.GetType(service.Service), Type.GetType(service.Implementation));
}
//Other scopes here...
return services;
}
And call it in ConifigureServices like this:
services.AddFromConfigurationFile(Configuration.GetSection("Services"));
So, nice and simple right? Why shouldn't you do this? A few ideas off the top of my head:
Why change how almost all DI implementations work? If it ain't broke, why fix it? Just because you are used to a particular method, doesn't mean it's a good idea.
Type safety: You lose compile time checking of the types you specify in the configuration file.
Security: Having this in a config file would let someone change the implementation to a class of their own choice.
I'm sure there are more, but... it's your app!

ASP.NET Core MVC App Settings

I'm trying to use configuration variables on my ASP.NET Core MVC project.
This is where I've got so far:
Created an appsettings.json
Created an AppSettings class
Now I'm trying to inject it on the ConfigureServices, but my Configuration class is either not recognized or when using the full reference: "Microsoft.Extensions.Configuration" the GetSection Method is not recognized, i.e.
Configuration class not being recognized
GetSection method not being recognized
Any ideas on how to use this?
The whole configuration approach in .NET Core is really flexible, but not at all obvious at the beginning. It's probably easiest to explain with an example:
Assuming an appsettings.json file that looks like this:
{
"option1": "value1_from_json",
"ConnectionStrings": {
"DefaultConnection": "Server=,\\SQL2016DEV;Database=DBName;Trusted_Connection=True"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}
To get the data from appsettings.json file you first need to set up a ConfigurationBuilder in Startup.cs as follows:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
if (env.IsDevelopment())
{
// For more details on using the user secret store see https://go.microsoft.com/fwlink/?LinkID=532709
builder.AddUserSecrets<Startup>();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
You can then access the configuration directly, but it's neater to create Options classes to hold that data, which you can then have injected into your controller or other classes. Each of those options classes represent a different section of the appsettings.json file.
In this code the connections strings are loaded into a ConnectionStringSettings class and the other option is loaded into a MyOptions class. The .GetSection method gets a particular part of the appsettings.json file. Again, this is in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
... other code
// Register the IConfiguration instance which MyOptions binds against.
services.AddOptions();
// Load the data from the 'root' of the json file
services.Configure<MyOptions>(Configuration);
// load the data from the 'ConnectionStrings' section of the json file
var connStringSettings = Configuration.GetSection("ConnectionStrings");
services.Configure<ConnectionStringSettings>(connStringSettings);
These are the classes that the settings data are loaded into. Note how the property names pair up with the settings in the json file:
public class MyOptions
{
public string Option1 { get; set; }
}
public class ConnectionStringSettings
{
public string DefaultConnection { get; set; }
}
Finally, you can then access those settings by injecting an OptionsAccessor into the controller as follows:
private readonly MyOptions _myOptions;
public HomeController(IOptions<MyOptions > optionsAccessor)
{
_myOptions = optionsAccessor.Value;
var valueOfOpt1 = _myOptions.Option1;
}
Generally, the whole configurations settings process is pretty different in Core. Thomas Ardal has a good explanation of it on his site here: http://thomasardal.com/appsettings-in-asp-net-core/
There's also a more detailed explanation of Configuration in ASP.NET Core in the Microsoft documentation.
NB: This has all evolved a bit in Core 2, I need to revisit some of the answer above, but in the meantime this Coding Blast entry by Ibrahim Ĺ uta is an excellent introduction with plenty of examples.
NB No. 2: There are a number of configuration mistakes that are easy to make with the above, have a look at this answer if it doesn't behave for you.
tomRedox 's answer was highly helpful - Thanks.
Also, I've changed the following references to the following versions, to get it working.
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.2",
"Microsoft.Extensions.Configuration.Json": "1.1.1"