Description
Background and Motivation
The implementation of DefaultProblemDetailsWriter
strictly enforces that ProblemDetails
are only written if Accept
is present and can be content negotiated. This is contrary to the HTTP specification. RFC 7231 §5.3.2 semantics for the Accept
header states:
...disregard the header field by treating the response as if it is not subject to content negotiation.
The current behavior is very sensible as a default. It requires a client to understand they can get a ProblemDetails
response; however, it is very common for API authors to not honor content negotiation for errors.
DefaultProblemDetailsWriter
is internal
and sealed
with functionality that cannot be easily extended or customized. Ultimately, an API author simply wants to decide if content negotiation should take place for ProblemDetails
and that shouldn't require customization when trivial configuration will suffice.
Proposed API
The proposed API would be to extend ProblemDetailsOptions
to include a property to determine whether content negotiation should be used. The default value will be true
, which retains the current behavior. If a developer sets the value to false
, the expectation is that content negotiation is skipped.
public class ProblemDetailsOptions
{
/// <summary>
/// The operation that customizes the current <see cref="Mvc.ProblemDetails"/> instance.
/// </summary>
public Action<ProblemDetailsContext>? CustomizeProblemDetails { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether to use HTTP content negotiation.
+ /// </summary>
+ /// <value>True if the content negotiation is used; otherwise, false. The default value is <c>true</c>.</value>
+ public bool UseContentNegotiation { get; set; } = true;
}
Usage Examples
The default configuration where content negotiation is used. This is the same behavior as today.
builder.Services.AddProblemDetails();
A new configuration option which can instruct IProblemDetailsWriter
implementations not to honor content negotiation.
builder.Services.AddProblemDetails(options => options.UseContentNegotiation = false);
Risks
Nothing apparent. The default configuration and behavior would be retained.
Additional Information
In accordance with RFC 7231 §5.3.2, if Accept
is unspecified or is empty, then the value of ProblemDetailsOptions.UseContentNegotiation
should be ignored and implied to be false
. This behavior is being tracked in #45051.