Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
271 views
in Technique[技术] by (71.8m points)

reactjs - SignalR and React - Invocation canceled due to the underlying connection being closed

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.

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 addComment() in the mobx store.

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

The error:

[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)

Here are the codes:

startup:

public class Startup
    {
            // only showing the codes related to problem
            services.AddSignalR();
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(opt =>
                {
                    opt.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = key,
                        ValidateAudience = false,
                        ValidateIssuer = false
                    };
                    opt.Events = new JwtBearerEvents
                    {
                        OnMessageReceived = context => 
                        {
                            var accessToken = context.Request.Query["access_token"];
                            var path = context.HttpContext.Request.Path;
                            if (!string.IsNullOrEmpty(accessToken) && 
                                (path.StartsWithSegments("/chat")))
                            {
                                context.Token = accessToken;
                            }
                            return Task.CompletedTask;
                        }
                    };
                });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseMiddleware<ErrorHandlingMiddleware>();
            if (env.IsDevelopment())
            {
                // app.UseDeveloperExceptionPage();
            }

            // app.UseHttpsRedirection();

            app.UseRouting();
            app.UseCors("CorsPolicy");

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapHub<ChatHub>("/chat");
            });
        }
    }

ChatHub.cs:

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 => 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("ReceiveComment", comment);
        }
    }

the mobx store where the connection is built:

  @observable comments: IComment[] | null = null;
  @observable.ref hubConnection: HubConnection | null = null;

  @action createHubConnection = () => {
    this.hubConnection = new HubConnectionBuilder()
      .withUrl("http://localhost:5000/chat", {
        accessTokenFactory: () => this.rootStore.commonStore.token!,
      })
      .configureLogging(LogLevel.Information)
      // i have to do this for now. Need to fix that disconnecting right
      // after Clients.All.SendAsync("ReceiveComment", comment); in ChatHub.cs
      // .withAutomaticReconnect([0, 0, 10000])
      .build();
    
    this.hubConnection
      .start()
      .then(() => console.log(this.hubConnection!.state))
      .catch((error) => console.log("Error establishing connection: ", error));

    this.hubConnection.on("ReceiveComment", (comment) => {
      runInAction(() => {
        if (this.comments == null) {
          this.comments = new Array<IComment>();
        }
        this.comments.push(comment);
      });
    });
  };

  @action stopHubConnection = () => {
    this.hubConnection!.stop();
  };
  
  @action addComment = async (values: any) => {
    try {
      await this.hubConnection!.invoke("SendComment", values);
    } catch (error) {
      console.log(error);
    }
  };

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...