dotnet / dotnet/aspnetcore

`TypedResults.ValidationProblem` should allow different status codes

Open
#67,696 10 comments 0 reactions 0 assignees View on GitHub
area-minimal feature-problem-details Needs: Attention :wave:
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 5h
Merged PRs (30d)
276

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Is your feature request related to a problem? Please describe the problem.

I'm trying to use `TypedResults.ValidationProblem()` to return a validation problem that has HTTP status code 422 (Unprocessable Entity). But the API doesn't allow me to specify a status code.
The return type `Microsoft.AspNetCore.Http.HttpResults.ValidationProblem` even explicitly disallows other status codes (see [source](https://github.com/dotnet/aspnetcore/blob/main/src/Http/Http.Results/src/ValidationProblem.cs)).

### Describe the solution you'd like

I'd like to have an `int? statusCode = null` parameter on the overloads of the method `TypedResults.ValidationProblem()`.
Alternatively, I'd like to have a new `TypedResults.ValidationProblem()` overload that accepts a `HttpValidationProblemDetails` parameter.

In both cases, the class `ValidationProblem` should then use the passed status code both in the response header and in the `status` property of the returned `HttpValidationProblemDetails` body.

It would be great if that status code could also be used for the OpenAPI metadata. But after reading through #52424 I understand that this might not be possible. Therefore the OpenAPI metadata could remain with status code 400. I'd then have to provide my status code in a different way for the OpenAPI document (like `.ProducesValidationProblem(StatusCodes.Status422UnprocessableEntity)` in minimal APIs or `[ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]` in API controllers).

Alternative:
If this suggestion won't be implemented then please at least consider making it easier to create a custom `ValidationProblem` class. For example, `ValidationProblem` could inherit from a base class so that we can create our own inherited class from it.
Or alternatively unseal `ValidationProblem` and allow overwriting the status code specific parts.

### Additional context

To explain why I want this: I'd like to differentiate between two types of validation problems:
- Bad requests/validation problems that are caused because of programming errors in the client. Those should be returned as status 400 Bad Request.
- Validations errors that are violations of business rules. Those should be returned as 422 Unprocessable Entity.

Quote from https://datatracker.ietf.org/doc/html/rfc4918#section-11.2 (emphasis mine):

> The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415 (Unsupported Media Type) status code is inappropriate), and **the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate)** but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

Other return types allow this:
- API controller `ActionResult` return types and `controller.ValidationProblem()` overloads allow specifing a status code.
- `IResult` return types and `Results.ValidationProblem()` overloads allow specifing a status code too.

But it is **not** possible with `ValidationProblem` (and therefore `Results`) return types and `TypedResults.ValidationProblem()` overloads.

Cc @DamianEdwards because he added this in #41161

Contributor guide

Open the contributing guide

Research direction

Start with src/Http/Http.Results/src/ValidationProblem.cs and the TypedResults.ValidationProblem() overloads described in the issue. Trace how the status code is fixed in the response header and HttpValidationProblemDetails body, then determine the compatible API change; done means callers can use a non-400 status such as 422 consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
backend-api-design
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.