NeonLog.CSharp.AspNetCore 0.1.0-ci.78

This is a prerelease version of NeonLog.CSharp.AspNetCore.
dotnet add package NeonLog.CSharp.AspNetCore --version 0.1.0-ci.78
                    
NuGet\Install-Package NeonLog.CSharp.AspNetCore -Version 0.1.0-ci.78
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="NeonLog.CSharp.AspNetCore" Version="0.1.0-ci.78" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NeonLog.CSharp.AspNetCore" Version="0.1.0-ci.78" />
                    
Directory.Packages.props
<PackageReference Include="NeonLog.CSharp.AspNetCore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add NeonLog.CSharp.AspNetCore --version 0.1.0-ci.78
                    
#r "nuget: NeonLog.CSharp.AspNetCore, 0.1.0-ci.78"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package NeonLog.CSharp.AspNetCore@0.1.0-ci.78
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=NeonLog.CSharp.AspNetCore&version=0.1.0-ci.78&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=NeonLog.CSharp.AspNetCore&version=0.1.0-ci.78&prerelease
                    
Install as a Cake Tool

NeonLog.CSharp.AspNetCore

ASP.NET Core request logging middleware for neonlog-c. Writes a structured completion log event for every HTTP request, with dynamic level selection and automatic population of NeonLogHttpRequestContext for downstream enrichers.

Quick start

using NeonLog.AspNetCore;

var builder = WebApplication.CreateBuilder(args);

// Register NeonLog as the logging provider
builder.Logging.AddNeonLog(builder.Configuration.GetSection("NeonLog"));

var app = builder.Build();

// Add request logging middleware (early in the pipeline)
app.UseNeonLogRequestLogging();

app.MapControllers();
app.Run();

Each request produces a log event like:

INF  HTTP GET /api/orders responded 200 in 42ms

Configuration

NeonLogRequestLoggingOptions

Member Type Default Description
GetLevel Func<HttpContext, long, Exception?, NeonLogLevel>? Intelligent default (see below) Determines the log level per request
EnrichDiagnosticContext Action<IDictionary<string, object?>, HttpContext>? null Add extra properties from HttpContext
MessageTemplate string "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {ElapsedMilliseconds}ms" Structured message template

Default GetLevel behaviour

When no delegate is provided, the middleware uses the same logic as the Serilog UseSerilogRequestLogging example:

Condition Level
Exception thrown Error
Response status code > 499 Error
Path is / or starts with /health Verbose
Everything else Information

Override with a custom delegate:

app.UseNeonLogRequestLogging(options =>
{
    options.GetLevel = (httpContext, elapsedMs, ex) =>
    {
        if (ex != null) return NeonLogLevel.Error;
        if (httpContext.Response.StatusCode > 499) return NeonLogLevel.Error;

        var path = httpContext.Request?.Path.Value?.ToLowerInvariant();
        if (path == "/" || (path?.StartsWith("/health") ?? false))
            return NeonLogLevel.Verbose;

        return httpContext.Request.Method == "GET"
            ? NeonLogLevel.Debug
            : NeonLogLevel.Information;
    };
});

Adding custom properties via EnrichDiagnosticContext

Use the EnrichDiagnosticContext callback to attach properties from HttpContext that aren't captured automatically:

app.UseNeonLogRequestLogging(options =>
{
    options.EnrichDiagnosticContext = (props, ctx) =>
    {
        props["CustomHeader"] = ctx.Request.Headers["X-Custom"].ToString();
    };
});

Properties added here are attached to the request completion log event via BeginScope, so they appear alongside the template parameters.

Custom message template

app.UseNeonLogRequestLogging(options =>
{
    options.MessageTemplate =
        "[{RequestMethod}] {RequestPath} -> {StatusCode} ({ElapsedMilliseconds}ms)";
});

How it works

  1. On request arrival, the middleware populates NeonLogHttpRequestContext with data extracted from HttpContext (method, path, user-agent, client IP, etc.).
  2. It calls _next(context) and measures elapsed time with Stopwatch.
  3. After the response, it updates the ambient context with the status code and elapsed time.
  4. The GetLevel delegate determines the log level.
  5. A structured log event is written via ILogger<RequestLoggingMiddleware>.

Properties populated by the middleware

The middleware sets every field on NeonLogHttpRequestData from HttpContext:

Property Source Example
RequestMethod context.Request.Method "GET"
RequestPath context.Request.Path "/api/orders"
RequestId context.TraceIdentifier "0HMKJ0KQ3T7C7"
CorrelationId context.TraceIdentifier "0HMKJ0KQ3T7C7"
Host context.Request.Host "example.com:443"
Protocol context.Request.Protocol "HTTP/1.1"
ContentType context.Request.ContentType "application/json"
UserAgent User-Agent header "Mozilla/5.0 …"
ClientIp context.Connection.RemoteIpAddress "192.168.1.100"
UrlReferrer Referer header "https://example.com/cart"
RawUrl Scheme + Host + Path + QueryString "https://example.com/api/orders?page=1"
UriQuery context.Request.QueryString "?page=1"
UserName context.User.Identity.Name or "(anonymous)" "alice"
StatusCode Set after response via SetStatusCode() 200
Elapsed Set after response via SetElapsed() 42

Integration with the HttpRequest enricher

Because the middleware sets NeonLogHttpRequestContext, any downstream code that logs within the same request automatically gets HTTP request properties attached — provided the HttpRequest enricher is configured:

// In NeonLog options:
options.Enrichers.Add(NeonLogBuiltInEnricher.HttpRequest);

Each log event within the request context will receive the following properties (both neonlog-c native names and HSSerilog-compatible aliases are emitted):

Native property HSSerilog alias
RequestMethod
RequestPath HttpRequestUriStem
RequestId
CorrelationId CorrelationId
Host
Protocol
ContentType HttpRequestContentType
UserAgent HttpRequestUserAgent
ClientIp HttpRequestClientHostIP
UrlReferrer HttpRequestUrlReferrer
RawUrl HttpRequestRawUrl
UriQuery HttpRequestUriQuery
UserName UserName
StatusCode
Elapsed
RequestBody HttpRequestBody

Note: HttpRequestBody is only populated if you add middleware that reads the request body and sets RequestBody on the ambient context.

API

IApplicationBuilder.UseNeonLogRequestLogging()

Registers RequestLoggingMiddleware with default options. Place early in the pipeline (after exception handling, before routing) so it captures the full request/response cycle.

IApplicationBuilder.UseNeonLogRequestLogging(Action<NeonLogRequestLoggingOptions>)

Registers the middleware with a configuration delegate for custom level selection, enrichment, or message template.

Migrating from Serilog (HSSerilog)

If you are migrating from HSSerilog's RequestEnricher, the property names are fully compatible. The following HSSerilog property names are emitted as aliases alongside the native neonlog-c names:

HSSerilog property Source in middleware
CorrelationId context.TraceIdentifier
HttpRequestClientHostIP context.Connection.RemoteIpAddress
HttpRequestUrlReferrer Referer header
HttpRequestRawUrl Scheme + Host + Path + Query
HttpRequestUserAgent User-Agent header
HttpRequestUriStem context.Request.Path
HttpRequestUriQuery context.Request.QueryString
HttpRequestContentType context.Request.ContentType
HttpRequestBody request.RequestBody (set externally)
UserName context.User.Identity.Name or "(anonymous)"

No changes to your log queries or dashboards are needed.

NuGet

dotnet pack bindings/dotnet/NeonLog.CSharp.AspNetCore/NeonLog.CSharp.AspNetCore.csproj -c Release

Package version follows $(NeonLogPackageVersion) (default 0.1.0). The package has no native assets — it depends solely on the NeonLog.CSharp package for the native neonlog-c runtime.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-ci.78 62 6/8/2026
0.1.0-ci.75 52 6/8/2026
0.1.0-ci.73 63 6/5/2026
0.1.0-ci.70 55 6/5/2026
0.1.0-ci.66 53 6/4/2026
0.1.0-ci.64 51 6/4/2026
0.1.0-ci.63 47 6/4/2026
0.1.0-ci.61 64 6/3/2026