SignalR不再工作,因为升级到.net Core 3.1



我有一个websocket服务器应用程序,我最近从。net Core 2.1升级到3.1,然而,从那时起,协商似乎失败了。这是我的控制台显示的错误。

我尽我最大的努力去遵循所有关于如何最好地升级到3.1的微软文档。在下面的代码中,您可以找到我的c#服务器当前使用的所有包。我知道3.1你不需要参考SignalR包,因为Microsoft.AspNetCore.App已经足够了,但是我在别人的帖子上看到它帮助了他们,所以我试图把它添加到我的(没有运气)。

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.1.0" />
    <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.24" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.0.2105168" />
    <PackageReference Include="RabbitMQ.Client" Version="5.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.10" />
  </ItemGroup>
这是我的Startup类的代码:
public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public IConfiguration Configuration { get; }
        readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<ConnectionOptions>(Configuration.GetSection("MQConfig"));
            services.AddHostedService<LiveUpdaterService>();
            services.AddCors(options =>
            {
                options.AddPolicy(MyAllowSpecificOrigins,
                builder =>
                {
                    builder
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowAnyOrigin()
                    .AllowCredentials();
                });
            });
            //I also tried services.AddSignalR();
            services.AddSignalRCore();  
            services.AddMvc(options => options.EnableEndpointRouting = false)
                .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                //app.UseHsts();
            }
            app.UseCors(cors =>
            {
                cors.AllowAnyHeader();
                cors.AllowAnyOrigin();
                cors.AllowAnyMethod();
                cors.AllowCredentials();
            });
            app.UseStaticFiles();
            
            app.UseRouting();
           
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<LiveUpdateHub>("/liveupdatehub", options =>
                {
                    options.Transports =
                        HttpTransportType.WebSockets |
                        HttpTransportType.LongPolling;
                });
                endpoints.MapControllers();
            });
            app.UseMvc();
            
        }
}
这是我的JavaScript客户端的代码:
import { HubConnectionBuilder, LogLevel } from "@microsoft/signalr";
var connection;
var connected;
export default class LiveDataHub {
    connectWebSocket() {
        connection = new HubConnectionBuilder()
            .withUrl("http://localhost:5003/liveupdatehub")
            .configureLogging(LogLevel.Information)
            .withAutomaticReconnect()
            .build();
        
        //Disable button until connection is established
        document.getElementById("runTestButton").disabled = true;
        
        connection.onclose(function (error) {
            document.getElementById("runTestButton").disabled = true;
            connected = false;
            console.log(error)
            alert("There was a problem connecting to the backend, please try again");
        });
        
        connection
            .start()
            .then(function () {
                document.getElementById("runTestButton").disabled = false;
                console.log(connection);
                connected = true;
            })
            .catch(function (err) {
                alert("No connection could be made to the backend, please refresh: " + err.toString());
                connected = false;
                return console.error(err.toString());
            });
        return connection;
    }
到目前为止,对于服务器,我已经尝试移动Configure和ConfigureServices方法,因为我知道它们的顺序在3.1中很重要,但也许有一个位置我错过了。我还尝试添加了很多额外的配置方法,我从其他帖子中读到,比如(options =>选项。EnableEndpointRouting = false)或AddNewtonSoftJson().

对于客户端,我试图通过添加以下内容来跳过协商部分:

connectWebSocket() {
        
        connection = new HubConnectionBuilder()
            .withUrl("ws://localhost:5003/liveupdatehub", {
                    skipNegotiation: true,
                    transport: HttpTransportType.WebSockets
                  })
            .configureLogging(LogLevel.Information)
            .withAutomaticReconnect()
            .build();

但是控制台错误日志会变成这样。这就是为什么我认为SignalR是主要问题。

如果有人能帮我解决这个问题,我将非常感激!

所以一段时间后我发现了潜在的问题是什么。结果是,调用services.AddHostedService()会导致托管服务在SignalR连接建立之前被调用,并且因为我的LiveUpdaterService依赖于SignalR,它会导致整个连接崩溃。

注释该方法后,协商与我的应用程序的其余部分一起工作(除了LiveUpdaterService)。如果有人感兴趣的话,我通过这个链接找到了答案:https://github.com/Azure/azure-signalr/issues/909。我目前正试图找到一个解决这个问题的解决方案,但至少现在连接正在工作。

我将此标记为已解决,因为addhostdservice更多的是一个兼容性问题。希望这能帮助到有同样问题的人。

我的Startup的最终代码:

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public IConfiguration Configuration { get; }
        readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddSignalR();
            
            services.Configure<ConnectionOptions>(Configuration.GetSection("MQConfig"));
            services.AddCors(options =>
            {
                options.AddPolicy("AllowSetOrigins",
                builder =>
                {
                    builder
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowCredentials()
                    .WithOrigins("http://localhost:5003")
                    .WithOrigins("http://localhost:8080");
                });
            });
            //services.AddHostedService<LiveUpdaterService>();
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            //app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseCors("AllowSetOrigins");
            app.UseAuthorization();
            app.UseAuthentication();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapHub<LiveUpdateHub>("/liveupdatehub");
            });
        }
    }

包的最终代码:

<ItemGroup>
  <FrameworkReference Include="Microsoft.AspNetCore.App" />
  <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
  <PackageReference Include="RabbitMQ.Client" Version="5.2.0" />
</ItemGroup>

最新更新