从 ASP.NET Core 中的 WebSocket 请求返回什么 IActionResult?

And*_*ott 4 c# websocket asp.net-core-mvc asp.net-core

我正在运行 ASP.NET Core 2.1 webapi,它正在侦听 Web 套接字请求。我想return this.BadRequest()请求是否不是 WebSocket 升级。

[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();
    }
}
Run Code Online (Sandbox Code Playgroud)

但无论走成功路径还是失败路径,服务器都会抛出异常:

失败: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 context) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& range, Object& state, Boolean& isCompleted) 在 Microsoft.AspNetCore .Mvc.Internal.ResourceInvoker.InvokeResultFilters() 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker .Next(State& next、Scope& range、Object& state、Boolean& 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 context) 在 Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) 在 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();
    }
Run Code Online (Sandbox Code Playgroud)

And*_*ott 6

秘密是EmptyResult,没有this.Empty()办法。

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 new EmptyResult();
}
Run Code Online (Sandbox Code Playgroud)