Is there a way to configure Serilog sub loggers via configuration file? - asp.net

Currently I have all configuration written in code. I use subloggers for filtering and changing the storage of logging. Is there any way to do it from configuration file. Because I want to have a separate config file for every context in solution.

If the number of sub-loggers is fixed at build time, you can use configuration prefixes to do this:
Log.Logger = new LoggerConfiguration()
.ReadFrom.AppSettings() // default file
.WriteTo.Logger(lc => lc
.ReadFrom.AppSettings(filePath: "other1.config"))
.WriteTo.Logger(lc => lc
.ReadFrom.AppSettings(filePath: "other2.config"))
.CreateLogger();
There's no support in Serilog.Settings.AppSettings yet, but in theory there's nothing preventing it being added if someone's able to implement it.

Try this
Startup.cs / Global.asax.cs
Log.Logger = new LoggerConfiguration()
.WriteTo
.Logger(x => x.Filter
.ByIncludingOnly(logEvent => logEvent.Level == Serilog.Events.LogEventLevel.Error)
.ReadFrom
.AppSettings("error"))
.WriteTo
.Logger(x => x.Filter
.ByIncludingOnly(logEvent => logEvent.Level == Serilog.Events.LogEventLevel.Information)
.ReadFrom
.AppSettings("info")).CreateLogger()
Web.Config
<add key ="error:serilog:using:RollingFile" value="Serilog.Sinks.RollingFile"/>
<add key ="error:serilog:write-to:RollingFile.pathFormat" value="C:\log\error {Date}.txt"/>
<add key ="error:serilog:write-to:RollingFile.formatter" value="Serilog.Formatting.Json.JsonFormatter"/>
<add key ="info:serilog:using:RollingFile" value="Serilog.Sinks.RollingFile"/>
<add key ="info:serilog:write-to:RollingFile.pathFormat" value="C:\log\info {Date}.txt"/>
<add key ="info:serilog:write-to:RollingFile.formatter" value="Serilog.Formatting.Json.JsonFormatter"/>

Related

ASP.NET MVC CORS issue

I have an ASP.NET MVC application (.NET 4.6) where on one occasion I need to redirect to a different domain.
So the code is like this (only authenticated users can come to the controller):
public ActionResult UploadForDesign(int parcelId)
{
......
string url = "differentdomain/parcelId" ;
return ReDirect(url);
}
I am getting an error:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin'.....
Failed to load resource: net::ERR_FAILED
I did the following in the control before redirect call
HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
and I still get the same error.
Also I tried the following in web.config, but didn't help much.
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
Now I had another test bare ASP.NET MVC app (.NET 4.5.2) with no authentication, and the above code works fine. I checked all the code and it looks the same except authentication in place and the framework version.
Any idea what to do?
You can try to use the WithOrigins method on your CORS policy and add whatever domain you need:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder =>
.WithOrigins("http://localhost:4200/")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
});
Ahhh sorry. I believe you should be able to use something like:
var p = new CorsPolicy();
p.AllowAnyHeader = true;
p.AllowAnyMethod = true;
p.AllowAnyOrigin = false;
p.Origins.Add("http://localhost:4200/");

Manage logging configuration with NLog in .NET Core 3

I'm using NLog in a .NET Core 3.1 worker service application.
Following the tutorial of NLog I inserted an nlog.config file to manage the configuration.
Now I'm confused because I have three points where I configure the logging:
In the code where I need to create a logger in a dependency injection context
// Other code...
services.AddScoped<IApplyJcdsCommandsJob, ApplyJcdsCommandsJob>(provider =>
{
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.ClearProviders()
.AddFilter("Microsoft", Microsoft.Extensions.Logging.LogLevel.Trace)
.AddFilter("System", Microsoft.Extensions.Logging.LogLevel.Trace)
.AddFilter("ApplyJcdsCommandsJob", Microsoft.Extensions.Logging.LogLevel.Trace)
//.AddConsole()
//.AddEventLog();
.AddNLog(configuration);
});
Microsoft.Extensions.Logging.ILogger logger = loggerFactory.CreateLogger<CommandsJob>();
return new CommandsJob(logger);
})
// Other code...
In appSettings.json
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Trace",
"System": "Trace",
"Microsoft": "Trace"
}
}
}
In NLog.config
The default config file produced by the nuget package installation:
<!-- a section of the config -->
<targets>
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="f" />
</rules>
<!-- ... -->
What I see is that if I remove the Nlog.config file, the log file will not be created.
Other changes seam to have no effect.
How are this configurations related?
What is the best way to switch on/off the logging and set the level?
People that decide to use NLog usually also want to disable all MEL-filtering to avoid the confusion with two filtering systems. So the NLog wiki-tutorial is targeted those users.
I guess people who are MEL-users first will probably just use new HostBuilder().CreateDefaultBuilder().Build() (Will setup everything with all guns enabled).
But if staying with the simple example, then you need to remove:
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
And add:
loggingBuilder.AddConfiguration(config.GetSection("Logging"));
So it looks like this:
serviceCollection.AddLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders();
loggingBuilder.AddConfiguration(config.GetSection("Logging"));
loggingBuilder.AddNLog(config);
})
ILoggingBuilder.AddConfiguration can be found at Nuget: Microsoft.Extensions.Logging.Configuration
AddNLog registers NLog like any other Microsoft Extension Logger (MEL) LoggingProvider (Similar to AddConsole).
This means NLog only gets log-output that has been "approved" by the MEL-ILogger. So any filtering configured in MEL will prevent logevents from reaching NLog.
NLog still has the ability to redirect based on Logger-names and LogLevel-severity to the wanted NLog-targets.
You can decide if you want to use MEL-Filtering or NLog-Filtering, or a combination of both. But if you just want to use "pure" NLog then just create an instance of NLog.Extensions.Logging.NLogLoggerFactory. It is a specialized ILoggerFactory that ignores MEL-Filtering-Configuration.
Btw. it is a little weird that you create an isolated LoggerFactory for each CommandsJob-instance. Would think that you would register the type in the dependency injection-framework, and let it inject constructor-parameters. See also this example:
https://github.com/NLog/NLog.Extensions.Logging/blob/master/examples/NetCore2/ConsoleExample/Program.cs
Where LoggerFactory is created with AddLogging(...) and where the Runner is registered in ServiceCollection for dependency-injection. When creating instance of Runner then dependency-injection will automatically provide ILogger as constructor-parameter.

Ckfinder azure set backend programmatically

I would like to set Azure as backend for CKFinder and I want to read values (account, password) from AppSettings, not CKFinder setting for backend.
smthng like:
<add key="CKFinderBackendAccountName" value="**********" />
<add key="CKFinderBackendAccountKey" value="************" />
So far I have this code and I want only Azure account, password to be read from APPSettings. I see no corresponding property in ConnectorBuilder.
connectorBuilder.LoadConfig()
.SetLicense(licenceDomain, licenceKey)
.SetAuthenticator(customAuthenticator)
.SetRequestConfiguration(
(request, config) =>
{
config.LoadConfig();
var defaultBackend = config.GetBackend("azureBackend");}

Need help getting [Authorize(Roles="Admin")] and User.isInRole("Admin") working in Asp.Net identity 1

I just don't get how these two potentially incredibly useful functions are supposed to work.
[Authorize(Roles="Admin")] //Method A
and
User.isInRole("Admin") //Method B
They are clearly not working right now for me. I did a few hours of research:
I read that you need to implement System.Web.Security.RoleProvider, then set it up in the web config:
<roleManager defaultProvider="OdbcRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All" >
<providers>
<clear />
<add
name="OdbcRoleProvider"
type="Samples.AspNet.Roles.OdbcRoleProvider"
connectionStringName="OdbcServices"
applicationName="SampleApplication"
writeExceptionsToEventLog="false" />
</providers>
</roleManager>
This caused the RoleProvider I implemented to by constructed, but the role checking functions were certainly not calling any of the methods in there.
I then read that Asp.NET Identity does away with the RoleProvider, now you need to do this:
<modules runAllManagedModulesForAllRequests="true">
<remove name="FormsAuthenticationModule" />
<remove name="RoleManager" />
</modules>
And I did that.
I have a custom UserManager that connects to my postgres backend. The problem is that whenever I use it, I need to instantiate one. It seems to me that if Functions A and B are going to work, then the UserManager I have implemented needs to be referenced in some sort of config file so Asp.NET knows about it implicitly. This would be just like the RoleManager in the past.
How does ASP.NET identity alter how Functions A and B check the roles from the old RoleProvider using behavior?
I figured it out.
When you call the login code like this:
var user = await UserManager.FindAsync(model.Email, model.Password);
if (user != null && user.PasswordRequiresReset == false)
{
await SignInAsync(user, model.RememberMe); //triggers IUserRoleStore.GetRolesAsync
return RedirectToLocal(returnUrl);
}
SignInAsync triggers GetRolesAsync from the IUserRoleStore:
public Task<IList<string>> GetRolesAsync(TUser user) //where TUser is an ApplicationUser
{
Func<object, IList<string>> getRoles = (object user2) =>
{
TUser user3 = (TUser)user2;
return user3.Roles.Select(x => x.Role.Name).ToList();
};
return Task.Factory.StartNew(getRoles, user);
}
In the above, I chose to simply generate the roles from the roles I already loaded from the db and stored in the ApplicationUser object when I created it in FindAsync.
The roles from GetRolesAsync must be loaded in the cookie somewhere where they can be accessed quickly and easily by Functions A and B.

Configure an OWIN static file server at a specific route prefix

I'm experimenting with keeping my content in non-default locations (eg in bower_components or /packages/../tools). As part of the experiment I am trying to set up an asp.net mvc 5 application where hitting a certain route allows me to browse files in the undersorejs package directory.
I have the following nuget packages (in addition to the default)
Install-Package underscore.js
Install-Package Microsoft.Owin.StaticFiles
Install-Package Microsoft.Owin.Host.SystemWeb
This is what I have in an OWIN startup class
var fileSystem = new PhysicalFileSystem(
HttpContext.Current.Server.MapPath("~")+"/../packages/underscore.js.1.6.0"
);
var options = new FileServerOptions {EnableDirectoryBrowsing = true, FileSystem = fileSystem};
app.MapWhen(ctx =>
ctx.Request.Uri.AbsolutePath.StartsWith("/__underscore"),
ab => ab.UseFileServer(options)
);
To my understanding and previous experimentation this is pretty straightforward - when the request begins with /__underscore use the simple static file server. However when I head over to /__underscore I get a 404 error.
However, placing breakpoints I can see that the UseFileServer lambda executes once on startup and then never again, while the predicate lambda is called on every request (and returns the correct value).
What am I missing?
You need to specify the RequestPath as well:
var options = new FileServerOptions {
EnableDirectoryBrowsing = true,
FileSystem = fileSystem,
RequestPath = PathString.FromUriComponent("/__underscore")
};
As per your comment:
If you're unable to download files, try to explicitly register OwinHttpHandler in your Web.Config:
<system.webServer>
<handlers>
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/>
</handlers>
</system.webServer>
Alternatively, you can set runAllManagedModulesForAllRequests to 'true':
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="FormsAuthenticationModule" />
</modules>
</system.webServer>

Resources