.Net 6 Preview 7 - Cannot set reponse headers before returning IAsyncEnumerable in controller
See original GitHub issueDescribe the bug
After updating from .Net 5 to .Net 6 Preview 7, I’m having an exception “System.InvalidOperationException: Headers are read-only, response has already started.” when trying to setup a response header before returning an IAsyncEnumerable. This error only occurs when making another async call in the process.
[HttpGet]
public async IAsyncEnumerable<WeatherForecastData> Get([EnumeratorCancellation] CancellationToken cancellationToken)
{
var results = await _dataService.GetData();
// System.InvalidOperationException: Headers are read-only, response has already started.
Response.Headers.Add("Test", results.Name);
await foreach (var result in results.Data.WithCancellation(cancellationToken))
{
yield return result;
}
}
My use case is that for pagination purposes before returning the IAsyncEnumerable I perform a query to get the total amount of data in the db, then place that pagination information as a response header for the client.
To Reproduce
Use this webapi minimal repository to reproduce
https://github.com/gabynevada/.net6-iasync-enumerable-set-header-error
Exceptions (if any)
Click to expand exception message
System.InvalidOperationException: Headers are read-only, response has already started.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ThrowHeadersReadOnlyException() in Microsoft.AspNetCore.Server.Kestrel.Core.dll:token 0x6000a43+0xa
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.System.Collections.Generic.IDictionary<System.String,Microsoft.Extensions.Primitives.StringValues>.Add(String key, StringValues value) in Microsoft.AspNetCore.Server.Kestrel.Core.dll:token 0x6000a5a+0x8
at System.Collections.Generic.CollectionExtensions.TryAdd[TKey,TValue](IDictionary2 dictionary, TKey key, TValue value) in System.Collections.dll:token 0x600005b+0x17 at SetResponseHeaders.Controllers.WeatherForecastController.Get(CancellationToken cancellationToken)+MoveNext() in /Users/elvis/Downloads/SetResponseHeaders/Controllers/WeatherForecastController.cs:line 27 at SetResponseHeaders.Controllers.WeatherForecastController.Get(CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult() in SetResponseHeaders.dll:token 0x6000014+0x0 at System.Threading.Tasks.ValueTask
1.ValueTaskSourceAsTask.<>c.<.cctor>b__4_0(Object state) in System.Private.CoreLib.dll:token 0x60033c6+0x23
— End of stack trace from previous location —
at System.Text.Json.Serialization.Converters.IAsyncEnumerableOfTConverter2.OnWriteResume(Utf8JsonWriter writer, TAsyncEnumerable value, JsonSerializerOptions options, WriteStack& state) in System.Text.Json.dll:token 0x6000970+0x95 at System.Text.Json.Serialization.Converters.IEnumerableDefaultConverter
2.OnTryWrite(Utf8JsonWriter writer, TCollection value, JsonSerializerOptions options, WriteStack& state) in System.Text.Json.dll:token 0x600099e+0x86
at System.Text.Json.Serialization.Converters.IAsyncEnumerableOfTConverter2.OnTryWrite(Utf8JsonWriter writer, TAsyncEnumerable value, JsonSerializerOptions options, WriteStack& state) in System.Text.Json.dll:token 0x600096f+0x14 at System.Text.Json.Serialization.JsonConverter
1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state) in System.Text.Json.dll:token 0x6000790+0x1f4
at System.Text.Json.Serialization.JsonConverter1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state) in System.Text.Json.dll:token 0x600077b+0x0 at System.Text.Json.Serialization.JsonConverter
1.WriteCoreAsObject(Utf8JsonWriter writer, Object value, JsonSerializerOptions options, WriteStack& state) in System.Text.Json.dll:token 0x600077a+0x49
at System.Text.Json.JsonSerializer.WriteCore[TValue](JsonConverter jsonConverter, Utf8JsonWriter writer, TValue& value, JsonSerializerOptions options, WriteStack& state) in System.Text.Json.dll:token 0x60003c6+0x18
at System.Text.Json.JsonSerializer.WriteAsyncCore[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken) in System.Text.Json.dll:token 0x60003d4+0xd4
at System.Text.Json.JsonSerializer.WriteAsyncCore[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken) in System.Text.Json.dll:token 0x60003d4+0x1b5
at System.Text.Json.JsonSerializer.WriteAsyncCore[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken) in System.Text.Json.dll:token 0x60003d4+0x38b
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) in Microsoft.AspNetCore.Mvc.Core.dll:token 0x6000b14+0x132
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) in Microsoft.AspNetCore.Mvc.Core.dll:token 0x6000a89+0x6a
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context) in Microsoft.AspNetCore.Mvc.Core.dll:token 0x6000a7c+0x15
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted) in Microsoft.AspNetCore.Mvc.Core.dll:token 0x6000a77+0x3dc
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultFilters>g__Awaited|28_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) in Microsoft.AspNetCore.Mvc.Core.dll:token 0x6000a88+0x6e
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) in Microsoft.AspNetCore.Mvc.Core.dll:token 0x6000a81+0x65
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) in Microsoft.AspNetCore.Mvc.Core.dll:token 0x6000a7d+0x77
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) in Microsoft.AspNetCore.Mvc.Core.dll:token 0x6000a7d+0xfb
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) in Microsoft.AspNetCore.Routing.dll:token 0x60000ab+0x5e
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) in Microsoft.AspNetCore.Authorization.Policy.dll:token 0x6000013+0x16b
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) in Swashbuckle.AspNetCore.SwaggerUI.dll:token 0x6000002+0x1ce
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) in Swashbuckle.AspNetCore.Swagger.dll:token 0x6000009+0x8e
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) in Microsoft.AspNetCore.Diagnostics.dll:token 0x60000aa+0x82
warn: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[2]
The response has already started, the error page middleware will not be executed.
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Further technical details
- ASP.NET Core version:
.Net 6 Preview 7
- Include the output of
dotnet --info
Click to view output
.NET SDK (reflecting any global.json): Version: 6.0.100-preview.7.21379.14 Commit: 22d70b47bc
Runtime Environment: OS Name: Mac OS X OS Version: 11.5 OS Platform: Darwin RID: osx.11.0-x64 Base Path: /usr/local/share/dotnet/sdk/6.0.100-preview.7.21379.14/
Host (useful for support): Version: 6.0.0-preview.7.21377.19 Commit: 91ba01788d
.NET SDKs installed: 5.0.100 [/usr/local/share/dotnet/sdk] 5.0.101 [/usr/local/share/dotnet/sdk] 5.0.102 [/usr/local/share/dotnet/sdk] 5.0.103 [/usr/local/share/dotnet/sdk] 5.0.202 [/usr/local/share/dotnet/sdk] 6.0.100-preview.7.21379.14 [/usr/local/share/dotnet/sdk]
.NET runtimes installed: Microsoft.AspNetCore.App 5.0.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.1 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.2 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.5 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.0-preview.7.21378.6 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App 5.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.1 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.2 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.0-preview.7.21377.19 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
- The IDE (VS / VS Code/ VS4Mac) you’re running on, and its version:
VsCode 1.59.0
Issue Analytics
- State:
- Created 2 years ago
- Comments:28 (11 by maintainers)
You can also return a
Task<IAsyncEnumerable<T>>
would that help?https://github.com/aspnet/Announcements/issues/463
Documentation would be great! We will do that.