OnStarting cannot be set because the response has already started.
See original GitHub issueIs there an existing issue for this?
- I have searched the existing issues
Describe the bug
I’m trying to recreate a feature from a legacy api that supported jsonp as a middleware in .net 7. What I have written appears to work fine when I initiate the request from the chrome browser but when using a node http client kestrel throws an invalidoperationexcpetion.
Expected Behavior
No matter the client, the middleware should modify the response without error.
Steps To Reproduce
i’ve registered this middleware at a few different spots in the pipeline and it doesn’t seem to matter.
#nullable enable
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace api.quirks;
public class JsonpMiddleware {
private readonly RequestDelegate _next;
public JsonpMiddleware(RequestDelegate next) {
_next = next;
}
public async Task InvokeAsync(HttpContext context) {
var version = context.GetRequestedApiVersion()!;
if (version > ApiVersion.Default) {
await _next(context);
return;
}
if (!context.Request.Query.TryGetValue("callback", out var callback)) {
await _next(context);
return;
}
if (!context.Response.HasStarted) {
context.Response.OnStarting(() => {
context.Response.ContentType = "text/javascript; charset=utf-8";
return Task.CompletedTask;
});
}
await context.Response.WriteAsync($"/**/ typeof {callback} === 'function' && {callback} (");
await _next(context); // this is the line that throws
await context.Response.WriteAsync(");");
await context.Response.Body.FlushAsync();
return;
}
}
Exceptions (if any)
[ERR 10:31:42] (Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware) An unhandled exception has occurred while executing the request.
System.InvalidOperationException: OnStarting cannot be set because the response has already started.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(String value)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.OnStarting(Func`2 callback, Object state)
at Microsoft.AspNetCore.Mvc.ReportApiVersionsAttribute.OnActionExecuting(ActionExecutingContext context)
at Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at CorrelationId.CorrelationIdMiddleware.Invoke(HttpContext context, ICorrelationContextFactory correlationContextFactory)
at api.quirks.JsonpMiddleware.InvokeAsync(HttpContext context) in .../JsonpMiddleware.cs:line 40
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
[WRN 10:31:42] (Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware) The response has already started, the error page middleware will not be executed.
.NET Version
7.0.202
Anything else?
No response
Issue Analytics
- State:
- Created 6 months ago
- Comments:5 (3 by maintainers)
Top Results From Across the Web
OnStarting cannot be set because the response has ...
The cause behind it is, Signin Manager makes use of HTTPContext to create cookies. at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.
Read more >Response is null if middleware return AuthenticateResult. ...
InvalidOperationException : StatusCode cannot be set because the response has already started. at Microsoft.AspNetCore.Server.Kestrel.Core.
Read more >Add Headers To A Response In ASP.NET 5
System.InvalidOperationException : Headers are read-only, response has already started. This exception occurs when our middleware takes the ...
Read more >Manipulating response headers in ASP.Net Core
First comes the status code, then come the headers and then comes the body. So if Asp.Net Core has started to write even...
Read more >Setting ASP.Net Cookies in Middleware
My searching led met to the Response.OnStarting method of the HttpResponse class. This method accepts a delegate to be invoked just before ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Try this:
You should not call WriteAsync and then call next. The next middleware isn’t expecting the response to have already started. If you need to wrap/modify the response body you’ll need to intercept the HttpResponse.Body Stream and do the modification inline or buffer and do it after next.