Мой вопрос в основном таков - учитывая приведенный здесь код, что еще работает в конвейере, который пытается начать ответ клиенту? Мне известны другие вопросы об этом исключении, но похоже, что что-то в конвейере, которое запускается после, вызывает исключение мое промежуточное программное обеспечение - оно не вызвано моим промежуточным программным обеспечением, которое, как мне кажется, является разница в моем сценарии.
Это простой эхо-сервер ASP.NET Core 3.0 WebSocket - без SignalR, без MVC, без маршрутизации, без поддержки статических страниц и т. Д. Помимо обработки сокетов, когда промежуточное ПО видит запрос на text/html
, оно отправляет обратно простая страница (жестко запрограммированная строка) в качестве эхо-клиента.
Браузер получает контент нормально, и мой обработчик исключений не запускается (критический момент), но после того, как мое промежуточное ПО завершит обработку запроса, ASP.NET Core регистрирует исключение:
StatusCode не может быть установлен, потому что ответ уже начался.
Код довольно минимален:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<WebSocketMiddleware>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
ReceiveBufferSize = 4 * 1024
};
app.UseWebSockets(webSocketOptions);
app.UseMiddleware<WebSocketMiddleware>();
}
}
public class WebSocketMiddleware : IMiddleware
{
// fields/properties omitted
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
try
{
if (context.WebSockets.IsWebSocketRequest)
{
// omitted, socket upgrade works normally
}
else
{
if(context.Request.Headers["Accept"][0].Contains("text/html"))
{
// this works but causes the exception later in the pipeline
await context.Response.WriteAsync(SimpleHtmlClient.HTML);
}
else
{
// ignore other requests such as favicon
}
}
}
catch (Exception ex)
{
// code omitted, never triggered
}
finally
{
// exception happens here
await next(context);
}
}
}
Я думал, что проблема может быть в том, что я использую WriteAsync
, но, похоже, это произойдет, если я также установлю статус HTTP в другом месте, без каких-либо других выходных данных, например, установка HTTP 500 в блоке catch
. Если я перейду через специально созданное исключение, добавив throw
в качестве самого первого оператора в промежуточном программном обеспечении, он попадет в finally
, где возникает исключение «уже запущено».
Так что еще пытается произвести вывод в конвейере с учетом этого класса Startup
?
Изменить: трассировка стека, строка 91, указанная в конце, - это await next(context)
в блоке finally
.
System.InvalidOperationException: StatusCode не может быть установлен, поскольку ответ уже начался. в Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException (значение String) в Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode (значение Int32sp) .Kestrel.Core.Internal.Http.HttpProtocol.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode (значение Int32) в Microsoft.AspNetCore.Http.DefaultHttpResponse.set_StatusCode. > c.b__18_0 (контекст HttpContext) в KestrelWebSocketServer.WebSocketMiddleware.InvokeAsync (контекст HttpContext, далее RequestDelegate) в C: \ Source \ WebSocketExample \ KestrelWebSocketServer \ WebSocketExample \ KestrelWebSocketServer \ WebSocketMiddleware. ‹B__1> d.MoveNext () --- Конец трассировки стека из предыдущего места, где было сгенерировано исключение --- в Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtoc ol.ProcessRequests [TContext] (приложение IHttpApplication`1)
IMiddleware
в данном случае). docs.microsoft.com/en- us / aspnet / core / basicals / middleware / - person McGuireV10   schedule 18.08.2019next
. Но возвращаясь к основному вопросу, что выполняется, когда я вызываюnext
, учитывая, что я ничего не добавил в конвейер. Очевидно, что сам ASP.NET делает больше под капотом - но что будет пытаться писать в этом сценарии? Кроме того, есть ли у вас какие-либо ссылки, которые могут прояснить ваш предыдущий комментарий о замене потока? Я ценю обратную связь. - person McGuireV10   schedule 18.08.2019await next
поставитьif(!context.Response.HasStarted)
, поскольку мой случай провала теоретически можно было бы обработать где-нибудь в другом месте. - person McGuireV10   schedule 18.08.2019