【问题标题】:How to work with SignalR in asp.net core 3.0如何在 asp.net core 3.0 中使用 SignalR
【发布时间】:2019-10-31 10:50:39
【问题描述】:

嗨,我们正在开发一个依赖于 Signal R 的 asp.net 核心项目。最后,我们将项目从 asp.net 核心 2.2 更新到 3.0,而 Signal R 停止工作。在文档中,我们配置了所有内容(我认为正确),但仍然无法正常工作。我们错过了什么?

Asp.net Core 3.0 API

启动:

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 项目

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();
  }
}

角度输出:

API 输出:

【问题讨论】:

  • 控制台有错误吗?如果您还没有升级 Angular SignalR 包到 3.0 版本,您还需要升级。
  • 我已经用控制台日志更新了我的问题
  • 我找不到包含 3.0 的包 nuget SignalR 的最新版本是 1.1.0
  • 在角度方面,我已将@aspnet/angular 更新为@microsoft/angular 3.0.0,但错误仍在继续

标签: c# angular typescript asp.net-core signalr


【解决方案1】:

只需使用 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");
            }
        });
    }

在 FE 方面。注意:使用新包@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));
    }
}

【讨论】:

    【解决方案2】:

    在托尼的帮助下,我终于想通了,

    显然 SignalR 聊天中心的方法出错了。这些方法只允许整数作为参数,但它必须是字符串。我不知道它与其他一些设置有关,但我现在的猜测是信号器无法将请求参数转换为字符串以外的东西。

    当我将其更改为字符串时,它起作用了。

    【讨论】:

      【解决方案3】:

      看来,您已经在服务器端配置了基于 JWT 的身份验证,并且没有为 SignalR 连接提供令牌。尝试使用 accessTokenFactory 提供令牌:

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

      【讨论】:

        猜你喜欢
        • 2020-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多