问题
In ASP.NET Core 3.1 a feature was added where unhandled exceptions can be passed onto an instance of ILogger as noted here: Logging in .NET Core and ASP.NET Core
I have a Server side Blazor website where I want to be able to process these exceptions in a function where I can log them to a database or perhaps send an email. However I am unable to come up with code to do this based on the provided documentation. Could someone provide sample code to trap unhandled exceptions?
回答1:
I recommand to use Serilog with sinks you need.
In your project add packages :
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Settings.Configuration
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.Debug
dotnet add package Serilog.Sinks.Seq
Serilog.AspNetCore to integrate Serilog with ASP.Net core.
Serilog.Settings.Configuration to read serilog config from .Net core configuration.
Serilog.Sinks.Console to write logs in the console.
Serilog.Sinks.Debug to write logs in Visual Studio output pane.
Serilog.Sinks.Seq to write logs in a Seq server, which is much more powerful than a DB.
Setup login in your Program.cs with :
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration))
.Build();
And in Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Admin/Error");
}
app.UseSerilogRequestLogging()
And configure your logs in appsettings.json with:
"Serilog": {
"LevelSwitches": {
"$controlSwitch": "Information"
},
"MinimumLevel": {
"ControlledBy": "$controlSwitch"
},
"WriteTo": [
{
"Name": "Seq",
"Args": {
"serverUrl": "http://localhost:5341/",
"controlLevelSwitch": "$controlSwitch",
"apiKey": "{SeqApiKey}"
}
},
{
"Name": "Console"
},
{
"Name": "Debug"
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithThreadId"
]
}
This tell Serilog to use the log level configure in Seq for your app.
"LevelSwitches": {
"$controlSwitch": "Information"
}
...
"Args": {
"serverUrl": "http://localhost:5341/",
"controlLevelSwitch": "$controlSwitch",
"apiKey": "{SeqApiKey}"
}
{SeqApiKey}
is an Api key configure in your Seq server for your app.
If you want to use a DB, Serilog has long list of sinks you can use.
回答2:
If you want to do it by yourself, on top of your middleware pipe add:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Admin/Error");
}
app.Use(async (context, next) =>
{
try
{
await next().ConfigureAwait(false);
}
catch(Exception e)
{
LogException(e);
throw;
}
})
回答3:
Doing some playing around, I found a way to do error logging without having to use a third party tool. Here is my code:
public class ExceptionLogger : ILogger
{
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return logLevel == LogLevel.Error;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if (logLevel == LogLevel.Error)
{
while (exception.InnerException != null)
exception = exception.InnerException;
LogException(exception);
}
}
private void LogException(Exception error)
{
...
}
public sealed class ExceptionLoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string categoryName)
{
return new ExceptionLogger();
}
public void Dispose()
{
}
}
And in Startup.cs add this:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddProvider(new ExceptionLoggerProvider());
...
来源:https://stackoverflow.com/questions/59413587/processing-unhandled-exceptions-in-asp-net-core-3-1