简体   繁体   English

如何在 asp.net 内核 3.0 中使用 SignalR

[英]How to work with SignalR in asp.net core 3.0

Hy, We're working on an asp.net core project that depends on Signal R.嗨,我们正在开发一个依赖于 Signal R 的 asp.net 核心项目。 lastly we updated our project from asp.net core 2.2 to 3.0 and the Signal R stopped working.最后,我们将项目从 asp.net 核心 2.2 更新到 3.0,并且 Signal R 停止工作。 In the documentation we configured everything (I think correctly) but is still doesn't work.在文档中,我们配置了所有内容(我认为是正确的),但仍然无法正常工作。 What did we miss?我们错过了什么?

Asp.net Core 3.0 API Asp.net 内核 3.0 API

Startup:启动:

public class Startup
{
     private readonly string corsPolicy = "CorsPolicy";
     private static string[] AllowdOrigins() => return new string[] {"localhost:4200","example.com"};

     public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            ConfigureAuthentication(services);


            ///MICROSOFT SQL DATABASE
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")
            ));

            services.Configure<ApiBehaviorOptions>(options =>
            {
                options.SuppressModelStateInvalidFilter = true;
            });

            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.KnownProxies.Add(IPAddress.Parse("XX.XX.XX.XX"));
            });

            services.AddSignalR();
            services.AddControllers();

            //services dependencies

        }


        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseCors(corsPolicy);

            //app.UseForwardedHeaders(new ForwardedHeadersOptions
            //{
            //    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
            //});

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


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



            DummyData.Initialize(app);
        }
        private void ConfigureAuthentication(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy(corsPolicy,
                builder =>
                {
                    builder
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowAnyOrigin()
                    .AllowCredentials()
                    .WithOrigins(AllowdOrigins());
                });
            });

            services.AddHttpContextAccessor();



            // configure strongly typed settings objects
            var appSettingsSection = Configuration.GetSection("AppSettings");
            services.Configure<AppSettings>(appSettingsSection);

            // configure jwt authentication
            var appSettings = appSettingsSection.Get<AppSettings>();
            var key = Encoding.ASCII.GetBytes(appSettings.Secret);

            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
            });
        }
}

Chathub:聊天室:

[EnableCors("CorsPolicy")]
    public class ChatHub : Hub
    {
        private static Dictionary<string, int> onlineClientCounts = new Dictionary<string, int>();
        private static readonly string FrontPrefix = "_FRONT";

        public ChatHub()
        {
        }

        [HubMethodName("ConnectFrontend")]
        public async Task ConnectFrontend(int sessionId)
        {

            //////
        }

        [HubMethodName("ConnectDevice")]
        public async Task ConnectDevice(int sessionId)
        {
            //// This method should be called but it isn't.
        }

        public void DisConnect(int sessionId, int userId)
        {
           //////////
        }

        [HubMethodName("SendJsonToFrontends")]
        public async Task SendJsonToFrontends(int sessionId, string jsonString)
        {
///
        }

        [HubMethodName("SendJsonToAll")]
        public async Task SendJsonToAll(int sessionId, string jsonString)
        {
////
        }
    }

Angular project Angular项目

SignalRService信号服务

export class SignalRService {

  private connection: signalR.HubConnection;

  public newMessage = new Subject<SocketMessage>();

  constructor() {

  }

  public connectFront() {

    this.connection = new signalR.HubConnectionBuilder()
        .withUrl("http://localhost:2525/chat")//(environment.baseSignalR)
        .configureLogging(signalR.LogLevel.Trace)
        .build();


    this.connection.on("ReceiveJson", data => { this.handleJsonMessage(data) });

    //handles the first connection message
    this.connection.start().then(() => this.sendConnectionMessage());

    //handles the incomming messages
    this.connection.on("ReceiveJson", data => this.handleJsonMessage(data));
    this.connection.on("ReceiveJsonFrontend", data => this.handleJsonMessage(data));
  }

  private sendConnectionMessage() {
    var sessionId = sessionStorage.getItem("SessionId");
    if (sessionId != null) {
        this.connection.invoke("ConnectFrontend", sessionId).catch((error) => { debugger; console.log(error); });
    }
  }

  public sendWebsocketMessageToAll(msg: SocketMessage) {
    var sessionId = sessionStorage.getItem("SessionId");
    if (sessionId != null) {
      this.connection.invoke("SendJsonToAll", sessionId, JSON.stringify(msg)).catch((error) => console.log(error));
    }
  }

  public sendWebsocketMessageToFrontend(msg: SocketMessage) {
    var sessionId = sessionStorage.getItem("SessionId");
    if (sessionId != null) {
      this.connection.invoke("SendJsonToFrontends", sessionId, JSON.stringify(msg)).catch((error) => console.log(error));
    }
  }

  private handleJsonMessage(data: string) {
    this.newMessage.next(this.getSocketMessage(data));
  }

  public getSocketMessage(data: string): SocketMessage {
    var msg: SocketMessage = JSON.parse(data);
    return msg;
  }

  public disconnect() {
    this.connection.stop();
  }
}

angular output: angular output: 在此处输入图像描述

Api output: Api output: 在此处输入图像描述

Just create an web app API with angular template you can view my code for your ref只需使用 angular 模板创建一个 web 应用程序 API 您可以查看我的代码为您的参考

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });
        services.AddSignalR().AddJsonProtocol(options =>
        {
            options.PayloadSerializerOptions.WriteIndented = false;
        });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
        }

        app.UseStaticFiles();
        if (!env.IsDevelopment())
        {
            app.UseSpaStaticFiles();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller}/{action=Index}/{id?}");
            endpoints.MapHub<ChatHub>("/chatHub");
        });

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    }

In FE side.在 FE 方面。 Note: use new package @microsoft/signalr注意:使用新的 package @microsoft/signalr

import * as signalR from "@microsoft/signalr";
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
    title = 'app';

    ngOnInit() {
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("/chathub")
            .build();

        connection.on("receiveMessage", (username: string, message: string) => {
            console.log(username);
            console.log(message);
        });

        connection.start().then(() => {
            connection.send("sendMessage", "aaa", "aaaa")
                .then(() => console.log("done"));

        }).catch(err => document.write(err));
    }
}

Well I finaly figured it out with the help of Tony,好吧,在托尼的帮助下,我终于想通了,

Apperently It went wrong in the methods of the SignalR chat hub.显然 SignalR 聊天中心的方法出错了。 The methods allowed only integers as parameters but it needed to be strings.这些方法只允许整数作为参数,但它必须是字符串。 I don't know it it has to do with some other settings but my guess now is that signalr cant convert the request parameters to something other then strings.我不知道它与其他一些设置有关,但我现在的猜测是 signalr 无法将请求参数转换为字符串以外的其他参数。

When I changed it to strings it worked.当我将其更改为字符串时,它起作用了。

It seems, that you have configured JWT based authentication on the server side and do not provide a token for SignalR connection.看来,您已经在服务器端配置了基于 JWT 的身份验证,并且没有为 SignalR 连接提供令牌。 Try to provide a token using the accessTokenFactory:尝试使用 accessTokenFactory 提供令牌:

this.hubConnection = new signalR.HubConnectionBuilder()
            .withUrl(`${environment.urlAddress}/chathub`, {
                accessTokenFactory: () => this.token
            })
            .build()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM