title: SignalR and React - Invocation canceled due to the underlying connection being closed
body: <p>Good evening.
  I am building a chat component using SignalR(5.0.1, I also tried an early version 3.0.0) and dotnet core 3.1.</p>
  <p>The comment that any of the users makes can be sent to all the connected clients, and all the connected clients can see the comment. However, the client which sent the comment will disconnect, and an error is caught <code>addComment() in the mobx store</code>.</p>
  <p>A client will lose its connection after sending a comment (the sender and the other clients can get the comment which has been processed from ChatHub). I don't know why the server decides to drop the connection and raise an error. I</p>
  <p>The error:</p>
  <pre><code>[2021-01-10T22:38:14.314Z] Information: Connection disconnected.
  adventureStore.ts:73 Error: Invocation canceled due to the underlying connection being closed.
      at HubConnection.connectionClosed (HubConnection.ts:654)
      at HttpConnection.HubConnection.connection.onclose (HubConnection.ts:103)
      at HttpConnection.stopConnection (HttpConnection.ts:488)
      at WebSocketTransport.transport.onclose (HttpConnection.ts:410)
      at WebSocketTransport.close (WebSocketTransport.ts:135)
      at WebSocket.webSocket.onclose (WebSocketTransport.ts:97)
  </code></pre>
  <p>Here are the codes:</p>
  <p>startup:</p>
  <pre><code>public class Startup
      {
              // only showing the codes related to problem
              services.AddSignalR();
              services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                  .AddJwtBearer(opt =&gt;
                  {
                      opt.TokenValidationParameters = new TokenValidationParameters
                      {
                          ValidateIssuerSigningKey = true,
                          IssuerSigningKey = key,
                          ValidateAudience = false,
                          ValidateIssuer = false
                      };
                      opt.Events = new JwtBearerEvents
                      {
                          OnMessageReceived = context =&gt; 
                          {
                              var accessToken = context.Request.Query[&quot;access_token&quot;];
                              var path = context.HttpContext.Request.Path;
                              if (!string.IsNullOrEmpty(accessToken) &amp;&amp; 
                                  (path.StartsWithSegments(&quot;/chat&quot;)))
                              {
                                  context.Token = accessToken;
                              }
                              return Task.CompletedTask;
                          }
                      };
                  });
          }
  
          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
          {
              app.UseMiddleware&lt;ErrorHandlingMiddleware&gt;();
              if (env.IsDevelopment())
              {
                  // app.UseDeveloperExceptionPage();
              }
  
              // app.UseHttpsRedirection();
  
              app.UseRouting();
              app.UseCors(&quot;CorsPolicy&quot;);
  
              app.UseAuthentication();
              app.UseAuthorization();
  
              app.UseEndpoints(endpoints =&gt;
              {
                  endpoints.MapControllers();
                  endpoints.MapHub&lt;ChatHub&gt;(&quot;/chat&quot;);
              });
          }
      }
  </code></pre>
  <p>ChatHub.cs:</p>
  <pre><code>public class ChatHub : Hub
      {
          private readonly IMediator _mediator;
          public ChatHub(IMediator mediator)
          {
              _mediator = mediator;
          }
  
          public async Task SendComment(Create.Command command)
          {
              var username = Context.User?.Claims?.FirstOrDefault(x =&gt; x.Type == 
              ClaimTypes.NameIdentifier)?.Value;
  
              command.Username = username;
  
              var comment = await _mediator.Send(command);
              
              // clients can successfully receive the comment and load it to their mobx store
              await Clients.All.SendAsync(&quot;ReceiveComment&quot;, comment);
          }
      }
  </code></pre>
  <p>the mobx store where the connection is built:</p>
  <pre><code>  @observable comments: IComment[] | null = null;
    @observable.ref hubConnection: HubConnection | null = null;
  
    @action createHubConnection = () =&gt; {
      this.hubConnection = new HubConnectionBuilder()
        .withUrl(&quot;http://localhost:5000/chat&quot;, {
          accessTokenFactory: () =&gt; this.rootStore.commonStore.token!,
        })
        .configureLogging(LogLevel.Information)
        // i have to do this for now. Need to fix that disconnecting right
        // after Clients.All.SendAsync(&quot;ReceiveComment&quot;, comment); in ChatHub.cs
        // .withAutomaticReconnect([0, 0, 10000])
        .build();
      
      this.hubConnection
        .start()
        .then(() =&gt; console.log(this.hubConnection!.state))
        .catch((error) =&gt; console.log(&quot;Error establishing connection: &quot;, error));
  
      this.hubConnection.on(&quot;ReceiveComment&quot;, (comment) =&gt; {
        runInAction(() =&gt; {
          if (this.comments == null) {
            this.comments = new Array&lt;IComment&gt;();
          }
          this.comments.push(comment);
        });
      });
    };
  
    @action stopHubConnection = () =&gt; {
      this.hubConnection!.stop();
    };
    
    @action addComment = async (values: any) =&gt; {
      try {
        await this.hubConnection!.invoke(&quot;SendComment&quot;, values);
      } catch (error) {
        console.log(error);
      }
    };
  </code></pre>