MagicCSharp.AspNetCore 1.0.2

dotnet add package MagicCSharp.AspNetCore --version 1.0.2
                    
NuGet\Install-Package MagicCSharp.AspNetCore -Version 1.0.2
                    
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="MagicCSharp.AspNetCore" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MagicCSharp.AspNetCore" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="MagicCSharp.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 MagicCSharp.AspNetCore --version 1.0.2
                    
#r "nuget: MagicCSharp.AspNetCore, 1.0.2"
                    
#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 MagicCSharp.AspNetCore@1.0.2
                    
#: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=MagicCSharp.AspNetCore&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=MagicCSharp.AspNetCore&version=1.0.2
                    
Install as a Cake Tool

MagicCSharp.AspNetCore

What a MagicCSharp web service needs from ASP.NET, and nothing else: a request id on every request, exceptions that leave as RFC 7807 problems instead of stack traces, and a startup check that resolves every registration before the first request does.

Separate from the core package so a worker, a console app or a message consumer using IMagicUseCase does not take a dependency on ASP.NET Core to get it. MagicCSharp.App makes all of these calls for you.

builder.Services.AddMagicErrorHandling();

var app = builder.Build();
app.Services.ValidateServices(builder.Services);   // preflight

app.UseRequestId();
app.UseMagicErrorHandling();
app.MapControllers();

Errors

A use case throws what it means; this is where that becomes a status code. Without it, a repository throwing NotFoundException for a row that is not there becomes a 500 with a stack trace — the framework would define the exception and then leave the caller to discover it as a server error.

Exception Status Title
HttpException and its subclasses whatever it carries the class name minus Exception
NotFoundException from the domain 404 NotFound
EntityConflictException from the domain 409 Conflict
EntityInvalidOperationException from the domain 422 InvalidOperation
ValidationException (DataAnnotations) 400 ValidationFailed
ArgumentException 400 BadRequest
OperationCanceledException 499 Cancelled
anything else 500 InternalServerError

The body is application/problem+json, with instance set to the path and a requestId extension carrying the same id the X-Request-ID header does — so a bug report quoting the body can be found in the logs. Outside Development a 500's detail is "An unexpected error occurred."; the exception itself goes to the log, because an unhandled exception's message routinely contains a connection string, a file path or a row nobody should see.

Logging is at the level the status implies: 5xx at Error with the exception, everything else at Information in one line. That is why this is plain middleware rather than UseExceptionHandler, which logs every exception it handles at Error — including the 404s and 409s that are routine — and makes an error dashboard useless. Put UseMagicErrorHandling first so it covers everything after it.

HttpException is for the times a use case genuinely means a status code:

BadRequestException 400
UnauthorizedException 401
ForbiddenException 403
HttpNotFoundException 404 — for a controller with no domain call to make; otherwise prefer the domain's NotFoundException, which maps here anyway
ConflictException 409
UnprocessableEntityException 422
TooManyRequestsException 429
HttpNotImplementedException 501

Derive your own for a status not listed. ErrorHandlingModule.Describe(exception, shouldIncludeDetail) is public, so a test can assert the mapping without a web host.

Request ids

app.UseRequestId();

Accepts an X-Request-ID header from the caller and generates one when there isn't one, puts it on the response, and makes it available through IRequestIdHandler for the life of the request — including across await, which is the part a plain field cannot do. A supplied id is echoed back only if it is short and printable; anything over 128 characters or carrying control characters is replaced, because it ends up in every log line for the request.

Put it before UseMagicErrorHandling, so the error handler's own log line and the requestId in the problem body carry the real id rather than Kestrel's connection counter.

Work that starts elsewhere sets its own. The Kafka listener sets a fresh request id per message, and the event dispatcher opens a logging scope per event and per handler, so a log line from three handlers deep still says which event it belongs to. IRequestIdHandler.SetRequestId() and SetChildRequestId() in the core package do the same for a job or a fan-out of your own.

Preflight

app.Services.ValidateServices(builder.Services);

Resolves every registered service once, from a throwaway scope, before the application starts serving. A missing or miswired dependency otherwise surfaces on the first request that happens to need it — which, in a service with a rarely-used endpoint, can be days after the deploy that broke it. Resolving everything at startup turns that into a failure the deploy itself reports.

It costs one construction of every singleton and scoped service. Call it once, after Build().

Note on the framework reference

This package uses <FrameworkReference Include="Microsoft.AspNetCore.App" /> rather than the Microsoft.AspNetCore.Http.Abstractions NuGet package. That package's last release is 2.2.0, from ASP.NET Core 2.2; referencing the shared framework gets the current types and adds nothing to the build output.

  • MagicCSharp.App — this, the core, events and scheduling, wired in two calls
  • MagicCSharp — use cases, IRequestIdHandler, NotFoundException

The whole picture: github.com/MagicDoorInc/MagicCSharp. MIT.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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 (1)

Showing the top 1 NuGet packages that depend on MagicCSharp.AspNetCore:

Package Downloads
MagicCSharp.App

Everything a MagicCSharp web service needs, wired in two calls. Brings in the core, ASP.NET, events and scheduling packages and registers use cases, TimeProvider, Snowflake IDs, request-ID tracking, in-process events, scheduling defaults, problem-details error handling and a startup preflight. Use the individual packages instead when you want to choose each piece.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.2 346 9/24/2026
1.0.1 98 9/24/2026
1.0.0 101 9/23/2026