`TypedResults.ValidationProblem` should allow different status codes
- 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
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