Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions samples/ProblemDetails.Sample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ private void ConfigureProblemDetails(ProblemDetailsOptions options)
// Only include exception details in a development environment. There's really no need
// to set this as it's the default behavior. It's just included here for completeness :)
options.IncludeExceptionDetails = (ctx, ex) => Environment.IsDevelopment();
options.IncludePropsFilter = (context, exception) => new IncludeProblemDetailProps()
{
Detail = true,
ExceptionDetails = true
};

// Custom mapping function for FluentValidation's ValidationException.
options.MapFluentValidationException();
Expand Down
15 changes: 12 additions & 3 deletions src/ProblemDetails/DeveloperProblemDetailsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,22 @@ namespace Hellang.Middleware.ProblemDetails
{
internal static class DeveloperProblemDetailsExtensions
{
public static MvcProblemDetails WithExceptionDetails(this MvcProblemDetails problem, string propertyName, Exception error, IEnumerable<ExceptionDetails> details)
public static MvcProblemDetails WithExceptionDetails(this MvcProblemDetails problem, string propertyName, Exception error, IEnumerable<ExceptionDetails> details, IncludeProblemDetailProps includeProps)
{
problem.Title ??= TypeNameHelper.GetTypeDisplayName(error.GetType());
problem.Extensions[propertyName] = GetErrors(details).ToList();

if (includeProps.ExceptionDetails)
{
problem.Extensions[propertyName] = GetErrors(details).ToList();
}

problem.Status ??= StatusCodes.Status500InternalServerError;
problem.Instance ??= GetHelpLink(error);
problem.Detail ??= error.Message;
if (includeProps.Detail)
{
problem.Detail ??= error.Message;
}

return problem;
}

Expand Down
19 changes: 19 additions & 0 deletions src/ProblemDetails/IncludeProblemDetailProps.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Hellang.Middleware.ProblemDetails
{
/// <summary>
/// Properties to include in ProblemDetails.
/// By default, all properties are false and will not be included.
/// </summary>
public class IncludeProblemDetailProps
{
/// <summary>
/// Include the Exception Details Stack
/// </summary>
public bool ExceptionDetails { get; set; }

/// <summary>
/// Include the Detail summary property
/// </summary>
public bool Detail { get; set; }
}
}
8 changes: 6 additions & 2 deletions src/ProblemDetails/ProblemDetailsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,16 @@ public ProblemDetailsFactory(
}
}

if (Options.IncludeExceptionDetails(context, error))
var includePropsFilter = Options.IncludePropsFilter?.Invoke(context, error);

if (Options.IncludeExceptionDetails(context, error) || includePropsFilter is not null)
{
try
{
includePropsFilter ??= new IncludeProblemDetailProps{ExceptionDetails = true, Detail = true};
// Instead of returning a new object, we mutate the existing problem so users keep all details.
return result.WithExceptionDetails(Options.ExceptionDetailsPropertyName, error, DetailsProvider.GetDetails(error));
return result.WithExceptionDetails(Options.ExceptionDetailsPropertyName, error,
DetailsProvider.GetDetails(error), includePropsFilter);
}
catch (Exception e)
{
Expand Down
8 changes: 8 additions & 0 deletions src/ProblemDetails/ProblemDetailsOptions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.FileProviders;
Expand Down Expand Up @@ -64,6 +65,13 @@ public ProblemDetailsOptions()
/// </summary>
public Func<HttpContext, Exception, bool> IncludeExceptionDetails { get; set; } = null!;

/// <summary>
/// Configure which properties to include in the problem details response.
/// By default all fields are excluded.
/// This can be used as an alternative to <see cref="IncludeExceptionDetails"/> when specific fields are needed.
/// </summary>
public Func<HttpContext, Exception, IncludeProblemDetailProps>? IncludePropsFilter { get; set; } = null!;

/// <summary>
/// The property name to use for traceId
/// This defaults to <see cref="DefaultTraceIdPropertyName"/> (<c>traceId</c>).
Expand Down