dotnet / dotnet/aspnetcore

Support setting HTTP response headers using some Results methods for Minimal APIs

Open
#39,585 3 comments 2 reactions 0 assignees View on GitHub
area-minimal
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.

Using Minimal APIs with the built-in [`Results`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.results?view=aspnetcore-6.0) class' methods allows for lots of built-in functionality to perform lots of operations a developer may wish to achieve with an HTTP endpoint, but the experience isn't as good as soon as you need to set an HTTP response header.

In this scenario you're left with at least three possible choices:

1. Mix and match use of `Results` with the `HttpResponse` so you can manually set any headers in the endpoint before returning the `IResult`.
2. Use `IResultExtensions` and a custom `IResult` implementation to write the body and any headers, likely duplicating implementation details from the internal `IResult` implementations.
3. Stop using the `Results` class and write to the content and headers to the `HttpResponse` directly in the endpoint.

As an example, take an endpoint which wishes to return an HTTP 429 problem if it wishes to rate limit the client and return a `Retry-After` response header. The [`Results.Problem()`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.results.problem?view=aspnetcore-6.0) can be used to return the body and set the status code, but there is no way to set the `Retry-After` header directly.

To achieve the desired result, you need to either mix-and-match the lower-level `HttpResponse` usage in the endpoint (and potentially add an extra parameter to access it) with the `Results` class, write a [custom extension](https://github.com/martincostello/polly-rate-limiting/blob/4c9aa22720557c8b30d62e6a3d208b12b7ae3008/src/TodoApp/ResultExtensions.cs#L8-L43), or not use `Results` at all.

The code would be simpler for the developer in non-advanced cases if they could pass through a simple key-value pair of strings through the `Results` methods to set HTTP response headers without having to add additional complexity and/or concepts, reducing the _"minimalness"_.

### Describe the solution you'd like

Some possible solutions to this (assuming it's not _do nothing_ as this is considered an advanced use case) could include:

1. Add a new overload or add another optional parameter to methods such as [`Results.Json()`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.results.json?view=aspnetcore-6.0) and [`Results.Problem()`](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.results.problem?view=aspnetcore-6.0) that accepts additional headers to set as an `IDictionary`, which would then be passed through to the internals of `ObjectResult` for use in the [`ConfigureResponseHeaders(HttpContext)`](https://github.com/dotnet/aspnetcore/blob/ef20668b82853a123ae9cf9f66af2bf67cc56f93/src/Http/Http.Results/src/ObjectResult.cs#L76-L78) method.
2. Make the `IResult` implementations public so behaviours could be easily overridden to extend them. For the HTTP 429 example, a developer could sub-class [`ObjectResult.ConfigureResponseHeaders(HttpContext)`](https://github.com/dotnet/aspnetcore/blob/ef20668b82853a123ae9cf9f66af2bf67cc56f93/src/Http/Http.Results/src/ObjectResult.cs#L76-L78) to set the additional header(s) (see also #37502)

### Additional context

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.