【发布时间】:2018-11-29 00:21:10
【问题描述】:
我有一个 ASP.NET Core 2.1 webapi 正在运行,它正在侦听 Web 套接字请求。如果请求不是针对 WebSocket 升级,我想 return this.BadRequest()。
[Route("api/[controller]")]
[ApiController]
public class SocketController : ControllerBase
{
[HttpGet]
public async Task<IActionResult> Post()
{
if (!this.HttpContext.WebSockets.IsWebSocketRequest)
return this.BadRequest();
using (var webSocket = await this.HttpContext.WebSockets.AcceptWebSocketAsync())
{
using (var jsonRpc = new JsonRpc(new WebSocketMessageHandler(webSocket)))
{
jsonRpc.AddLocalRpcTarget(new SocketServer());
jsonRpc.StartListening();
await jsonRpc.Completion;
}
}
return this.Ok();
}
}
但是无论是走成功路径还是失败路径,服务端都会抛出异常:
失败:Microsoft.AspNetCore.Server.Kestrel[13] 连接 ID“0HLEM87126JEO”,请求 ID“0HLEM87126JEO:00000001”:应用程序引发了未处理的异常。 System.InvalidOperationException:无法设置 StatusCode,因为响应已经开始。 在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(字符串值) 在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode(Int32 值) 在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 值) 在 Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.set_StatusCode(Int32 值) 在 Microsoft.AspNetCore.Mvc.StatusCodeResult.ExecuteResult(ActionContext 上下文) 在 Microsoft.AspNetCore.Mvc.ActionResult.ExecuteResultAsync(ActionContext 上下文) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult 结果) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsyncTFilter,TFilterAsync 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext 上下文) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters() 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext 上下文) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(状态&下一个,范围&范围,对象&状态,布尔& isCompleted) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() 在 Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext) 在 Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文) 在 Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文) 在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 应用程序)
如果我将方法更改为只返回 Task 就可以了,这样我就不必提供 IActionResult,但是我没有办法对错误请求返回 400 响应。解决此问题的最佳方法是什么?
我的中间件超级简单:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// app.UseHsts();
}
// app.UseHttpsRedirection();
app.UseWebSockets();
app.UseMvc();
}
【问题讨论】:
-
问题是 websocket 处理程序可能已经发送了一些东西来进行通信。我想有一种方法可以使用当前的 HttpContext 来提供响应,而不是通过从函数返回来提供响应。不过我对asp.net一无所知。
-
很可能由于套接字请求,管道中较高的中间件已经开始响应。应该在那里开始调查
-
谢谢,@nkosi。我的中间件超级简单。我已将其添加到我的问题中。
标签: c# asp.net-core websocket asp.net-core-mvc