Include exception in ProblemDetailsContext for controller error responses#65817
Include exception in ProblemDetailsContext for controller error responses#65817BloodShop wants to merge 7 commits intodotnet:mainfrom
Conversation
…nses When using ExceptionHandlerMiddleware with controllers, the CustomizeProblemDetails callback receives a ProblemDetailsContext with a null Exception. This happens because DefaultProblemDetailsFactory creates a new context internally without pulling the exception from the HttpContext features. The Minimal API path (DefaultProblemDetailsWriter) works correctly because it passes the original context — which already has the exception set by the middleware — straight through to the callback. The fix: in DefaultProblemDetailsFactory.ApplyProblemDetailsDefaults, resolve the exception from IExceptionHandlerFeature on the HttpContext before invoking the customize callback. When no exception handler feature is present (e.g., validation errors, manual status codes), the exception remains null as before. Changes: - DefaultProblemDetailsFactory: read exception from IExceptionHandlerFeature and set it on the ProblemDetailsContext - Add Diagnostics.Abstractions reference to Mvc.Core - Add tests verifying exception propagation in both scenarios Fixes dotnet#65697
|
Thanks for your PR, @@BloodShop. Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
The test file uses Exception? nullable annotations but was missing the #nullable enable directive, causing CS8632 compilation errors in CI. This fix enables nullable context for the test file to match the source file pattern and resolve the build failures.
|
🔧 Fixed CI Build Failures! Issue identified: CS8632 compilation errors due to missing directive in the test file. Fix applied: Added to to enable nullable reference type context, matching the pattern used in the source file. What this resolves:
The core implementation logic remains unchanged - this was purely a compilation issue. CI should now be green! 🚀 |
CI Failure Analysis - Flaky Test IssueThe current CI failure is unrelated to this PR's code changes: Failed Test: Evidence this is a known flaky test:
Files changed in this PR:
Previous fix applied: Added Request: Please consider re-running CI or merging despite the flaky test, as this follows the established precedent of PR #65897 which had identical infrastructure failures. The ProblemDetailsContext fix correctly addresses issue #65697 and provides exception access in controller scenarios. |
Summary
When using
ExceptionHandlerMiddlewarewith controllers andCustomizeProblemDetails, theProblemDetailsContext.Exceptionis alwaysnull. The same setup with Minimal APIs correctly populates the exception.Reproduction
context.Exceptionis alwaysnulleven though the exception is available.Root Cause
Two different code paths handle problem details writing:
Minimal APIs (
DefaultProblemDetailsWriter): CallsCustomizeProblemDetailsdirectly with the originalProblemDetailsContextfrom the middleware — which already has theExceptionset. Works correctly.Controllers (
DefaultApiProblemDetailsWriter→DefaultProblemDetailsFactory): The factory'sApplyProblemDetailsDefaultscreates a newProblemDetailsContextfor the callback, but never sets theExceptionproperty:The Fix
In
DefaultProblemDetailsFactory.ApplyProblemDetailsDefaults, resolve the exception fromIExceptionHandlerFeature(which theExceptionHandlerMiddlewaresets on theHttpContext) and include it in the context:When no
IExceptionHandlerFeatureis present (validation errors, manual status codes, etc.),exceptionisnull— same behavior as before.Changes
DefaultProblemDetailsFactory.csIExceptionHandlerFeatureonHttpContext.FeaturesProblemDetailsContextin the customize callbackMicrosoft.AspNetCore.Mvc.Core.csprojMicrosoft.AspNetCore.Diagnostics.Abstractions(forIExceptionHandlerFeature)ProblemDetailsFactoryTest.cs(tests)IExceptionHandlerFeatureis presentnullwhen no feature is presentBehavior After Fix
context.Exception == null❌context.Exception == <thrown>✅context.Exception == <thrown>✅context.Exception == nullcontext.Exception == nullBreaking Changes
None. The only change is that
ProblemDetailsContext.Exceptionis now populated where it was previouslynull. Code that checked forcontext.Exception is not nullwill now correctly enter that branch.Fixes #65697