ASP.NET NLog
ASP.NET.Core8\Program.cs
using System.Text.Json.Serialization;
using NLog.Web;
var builder = WebApplication.CreateSlimBuilder(args);
// 👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇
// Setup NLog for Logging
await using var nlogFactory = NLog.LogManager.LogFactory; // async flush/shutdown on dispose // 这行可以去除right
builder.Logging.ClearProviders();
builder.UseNLog();
//
builder.Services.AddHostedService<HeartbeatWorker>();
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});
var app = builder.Build();
// 👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇
var nlogger = NLog.LogManager.GetCurrentClassLogger();
nlogger.Info("NLog logger initialized in Program.cs");
var sampleTodos = new Todo[]
{
new(1, "Walk the dog"),
new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
new(3, "Do the laundry", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),
new(4, "Clean the bathroom"),
new(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2))),
};
var todosApi = app.MapGroup("/todos");
todosApi.MapGet(
"/",
(ILogger<Todo> logger) =>
{
logger.LogInformation("Generated {TodoList}", sampleTodos);
return sampleTodos;
}
);
todosApi.MapGet(
"/{id}",
(int id) =>
sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo
? Results.Ok(todo)
: Results.NotFound()
);
app.Run();
public record Todo(int Id, string? Title, DateOnly? DueBy = null, bool IsComplete = false);
[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext { }
ASP.NET.Core8\nlog.config
<?xml version="1.0" encoding="utf-8"?>
<nlog
xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info"
throwConfigExceptions="true"
internalLogFile="c:\temp\internal-nlog-AspNetCore8.txt"
>
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore" />
</extensions>
<!-- the targets to write to -->
<targets>
<!-- File Target for all log messages with basic details -->
<target
xsi:type="File"
name="allfile"
fileName="${basedir}/log/${shortdate}/${shortdate}-all.log"
layout="${longdate}|${event-properties:item=EventId:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}"
/>
<!-- File Target for own log messages with extra web details using some ASP.NET core renderers -->
<target
xsi:type="File"
name="ownFile-web"
fileName="${basedir}/log/${shortdate}/${shortdate}-aspnet.log"
layout="${longdate}|${event-properties:item=EventId:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}"
/>
<!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection -->
<target xsi:type="Console" name="lifetimeConsole" layout="${MicrosoftConsoleLayout}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="allfile" />
<!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) -->
<logger name="Microsoft.*" finalMinLevel="Warn" />
<logger name="System.Net.Http.*" finalMinLevel="Warn" />
<!--Output hosting lifetime messages to console target for faster startup detection -->
<logger name="Microsoft.Hosting.Lifetime" finalMinLevel="Info" writeTo="lifetimeConsole" />
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />
</rules>
</nlog>
{
"version": 1,
"isRoot": true,
"tools": {
"csharpier": {
"version": "1.0.3",
"commands": [
"csharpier"
],
"rollForward": false
}
}
}
ASP.NET.Core8\BackGroundServices\HeartbeatWorker.cs
public class HeartbeatWorker : BackgroundService
{
private readonly ILogger<HeartbeatWorker> _logger;
public HeartbeatWorker(ILogger<HeartbeatWorker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (true)
{
System.Console.WriteLine("----------------");
System.Console.WriteLine(stoppingToken.IsCancellationRequested);
System.Console.WriteLine(stoppingToken.CanBeCanceled);
if (stoppingToken.IsCancellationRequested)
{
break;
}
System.Console.WriteLine("background service");
_logger.LogInformation("background service");
await Task.Delay(3000);
}
}
}
ASP.NET.Core8\Properties\launchSettings.json
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "todos",
"applicationUrl": "http://localhost:5108",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
ASP.NET.Core8\appsettings.Development.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
ASP.NET.Core8\appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
ASP.NET.Core8\ASP.NET.Core8.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
<PublishAot>true</PublishAot>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
</PropertyGroup>
<ItemGroup>
<!-- <ProjectReference Include="..\..\src\NLog.Web.AspNetCore\NLog.Web.AspNetCore.csproj" /> -->
</ItemGroup>
<ItemGroup>
<PackageReference Include="NLog.Web.AspNetCore" Version="6.0.1" />
</ItemGroup>
</Project>
ASP.NET.Core8\ASP.NET.Core8.sln
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASP.NET.Core8", "ASP.NET.Core8.csproj", "{D4851670-1BF0-8A37-3F1E-AC033CAA233E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4851670-1BF0-8A37-3F1E-AC033CAA233E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4851670-1BF0-8A37-3F1E-AC033CAA233E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4851670-1BF0-8A37-3F1E-AC033CAA233E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4851670-1BF0-8A37-3F1E-AC033CAA233E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C933D0CB-E190-4A8F-978A-69AF1939F476}
EndGlobalSection
EndGlobal
dotnet csharpier format .
ASP.NET.Core8\run.bat
dotnet run