title: What IActionResult to return from a WebSocket request in ASP.NET Core?
body: <p>I have an ASP.NET Core 2.1 webapi running that is listening for web socket requests. I want to <code>return this.BadRequest()</code> if the request isn't for a WebSocket upgrade.</p>
  
  <pre><code>[Route("api/[controller]")]
  [ApiController]
  public class SocketController : ControllerBase
  {
      [HttpGet]
      public async Task&lt;IActionResult&gt; 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();
      }
  }
  </code></pre>
  
  <p>But whether it takes the success path or the failure path, the server throws an exception:</p>
  
  <blockquote>
    <p>fail: Microsoft.AspNetCore.Server.Kestrel[13]
          Connection id "0HLEM87126JEO", Request id "0HLEM87126JEO:00000001": An unhandled exception was thrown by the application.
    System.InvalidOperationException: StatusCode 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.set_StatusCode(Int32 value)
       at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 value)
       at Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.set_StatusCode(Int32 value)
       at Microsoft.AspNetCore.Mvc.StatusCodeResult.ExecuteResult(ActionContext context)
       at Microsoft.AspNetCore.Mvc.ActionResult.ExecuteResultAsync(ActionContext context)
       at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
       at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsyncTFilter,TFilterAsync
       at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
       at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State&amp; next, Scope&amp; scope, Object&amp; state, Boolean&amp; isCompleted)
       at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
       at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
       at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
       at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State&amp; next, Scope&amp; scope, Object&amp; state, Boolean&amp; isCompleted)
       at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
       at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
       at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
       at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
       at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
       at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)</p>
  </blockquote>
  
  <p>It works OK if I change the method to just return <code>Task</code> so I don't have to provide an <code>IActionResult</code>, but then I don't have a way to return a 400 response to bad requests. What is the best way to go about this?</p>
  
  <p>My middleware is super simple:</p>
  
  <pre><code>    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
      {
          if (env.IsDevelopment())
          {
              app.UseDeveloperExceptionPage();
          }
          else
          {
              // app.UseHsts();
          }
  
          // app.UseHttpsRedirection();
          app.UseWebSockets();
          app.UseMvc();
      }
  </code></pre>