Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure options to display StackTrace with AddProblemDetails() based on environment in ASP.NET Core?

I have my ASP.NET Core 9 Web API app using custom ExceptionHandlerMiddleware Middleware to handle all exceptions as shown below:

public sealed class ExceptionHandlerMiddleware(IWebHostEnvironment env, ILogger<ExceptionHandlerMiddleware> logger) : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        try
        {
            await next(context);
        }
        catch (DomainException ex)
        {
            await HandleDomainExceptionAsync(context, ex);
        }
        catch (DbUpdateException ex)
        {
            await HandleDbUpdateExceptionAsync(context, ex);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private Task HandleDomainExceptionAsync(HttpContext context, DomainException exception)
    {
        logger.LogCritical(exception, exception.Message);
        var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
        string result = JsonSerializer.Serialize(Envelope.Error(exception.Message), options);
        context.Response.ContentType = MediaTypeNames.Application.Json;
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        return context.Response.WriteAsync(result);
    }

    private Task HandleDbUpdateExceptionAsync(HttpContext context, Exception exception)
    {
        logger.LogCritical(exception, exception.Message);
        var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
        string result = JsonSerializer.Serialize(Envelope.Error("Error occurred while saving data. Please try again later."), options);
        context.Response.ContentType = MediaTypeNames.Application.Json;
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        return context.Response.WriteAsync(result);
    }

    private Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        logger.LogCritical(exception, exception.Message);
        var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
        string result = env.IsLocal() ? JsonSerializer.Serialize(Envelope.Error(exception.Message), options) : JsonSerializer.Serialize(Envelope.Error("An unexpected fault happened. Try again later."), options);
        context.Response.ContentType = MediaTypeNames.Application.Json;
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        return context.Response.WriteAsync(result);
    }
}

Now, I came across ProblemDetails and looks like ASP.NET Core 9 has support for it.

All I need to do is to,

Program.cs:

builder.Services.AddProblemDetails();

var app = builder.Build();

app.UseExceptionHandler();

app.Run();

The setup is easy and straight forward. But the problem is whenever I test with exception I get the below response.

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.6.1",
  "title": "An error occurred while processing your request.",
  "status": 500,
  "traceId": "00-a2cfefb5c6ca44a142d9810fef0e5f7d-d7103986bf2c06a4-00"
}

enter image description here

Now I need help in understanding how to show StackTrace in lower environments like Local, Offline, Development. I'm not able to find an option to configure StackTrace based on environment.

I checked the problem details docs and not able to find any information.

like image 762
fingers10 Avatar asked Dec 05 '25 15:12

fingers10


1 Answers

First of all, default template for ASP.NET Core project contains such lines:

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
    app.UseDeveloperExceptionPage();
}

which enables developer exception page in development mode. This page contains stack trace for example: enter image description here

If I would comment/remove app.UseDeveloperExceptionPage(), then i would get this in browser (this is just response body): enter image description here

So, this is one way to get more details about exceptions.

How to inlucde stack trace directly in problem details, without developer's exception page

You can adjust behavior of problem details with such overload of AddProblemDetails:

builder.Services.AddProblemDetails(options =>
{
    options.CustomizeProblemDetails = context =>
    {
        var hostEnv = context.HttpContext.RequestServices.GetRequiredService<IHostEnvironment>();

        var shouldIncludeStackTrace = hostEnv.IsDevelopment();

        if (context.Exception is null || !shouldIncludeStackTrace)
        {
            return;
        }

        context.ProblemDetails.Detail = context.Exception.StackTrace;
    };
});

With this change, you will get additional stack trace in details property in response, only in development environment: enter image description here

Last, but not least, you need to adjust condition:

var shouldIncludeStackTrace = hostEnv.IsDevelopment();

in order to inlcude stack trace only in environments, that need it.

References:

  • Customize problem details with CustomizeProblemDetails
like image 145
Michał Turczyn Avatar answered Dec 08 '25 06:12

Michał Turczyn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!