SignalR不再起作用,因为升级到.NET CORE 3.1

发布于 2025-01-21 14:18:45 字数 5804 浏览 1 评论 0原文

我有一个最近将.NET Core 2.1升级到3.1的WebSocket Server应用程序,但是从那时起,谈判似乎失败了。 这是我的控制台显示的错误。

我尽力在如何最好地升级到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>

这是我启动类的代码:

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

到目前为止,我尝试移动配置和配置方法,因为我知道它们的顺序在3.1中很重要,但是也许有一个位置i弗错过了。我还尝试了添加很多额外的配置方法,这些方法是从其他帖子中读取的,例如(options =&gt; options.enabledpointreting = false)或addNewtonsoftjson()。

对于客户,我尝试通过添加以下添加来跳过谈判部分:

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

,但是控制台错误日志,然后更改为这是这使我相信Signalr是这里的主要问题。

如果有人能帮助我,我将非常感谢!

I have a websocket server application that I recently upgraded from .NET Core 2.1 to 3.1, however, since then the negotiation seems to fail.
This is the error that my console shows.

I tried my best to follow all the Microsoft docs on how best to upgrade to 3.1. In the code below you can find all the packages my C# server currently uses. I know that with 3.1 you don't have to reference the SignalR packages since Microsoft.AspNetCore.App is enough, but I saw on someone else's post that it helped them so I tried to add it to mine (with no luck).

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

This is the code for my Startup class:

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

This is the code for my JavaScript client:

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

So far for the server, I've tried moving the Configure and ConfigureServices methods around because I know their order matters in 3.1, but maybe there's a position I've missed. I've also tried adding a lot of extra Configure methods that I read from other posts like (options => options.EnableEndpointRouting = false) or AddNewtonSoftJson().

For the client I've tried to skip the negotiation part by adding this:

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

But the console error log then changes to this. Which is what leads me to believe that SignalR is the main issue here.

If anyone can help me with this I'd really appreciate it!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

怪我闹别瞎闹 2025-01-28 14:18:45

因此,一段时间后,我发现了基本问题是什么。事实证明,呼叫services.addhostedService()会导致托管服务在建立SignalR连接之前被调用,并且因为我的LiveUpDaterService依赖Signalr依赖Signalr,所以它崩溃了整个连接。

在评论了该方法之后,谈判与我的其余应用程序(除了LiveUpDaterService)一起工作。如果有人有兴趣,我通过此链接找到了答案: https://github.com/ azure/azure-signalr/essugn/909 。我目前正在尝试为此找到解决方法,但是至少该连接现在正在起作用。

我将其标记为解决,因为AddhostedService更像是一个兼容性问题。希望这可以帮助其他人遇到同样的问题。

我的启动的最终代码:

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>

So after some time I've discovered what the underlying issue was. It turns out that calling services.AddHostedService() causes the hosted service to be called up before the SignalR connection can be established, and because my LiveUpdaterService relies on SignalR it crashes the whole connection.

After commenting that method out, the negotiation works along with the rest of my app (besides the LiveUpdaterService). I found the answer through this link if anyone is interested: https://github.com/Azure/azure-signalr/issues/909. I'm currently trying to find a workaround fix for this, but at least the connection is working now.

I'll marked this as solved since the AddHostedService is more of a compatibility issue. Hopefully this might help someone else with the same problem.

Final code for my 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");
            });
        }
    }

Final code for my packages:

<ItemGroup>
  <FrameworkReference Include="Microsoft.AspNetCore.App" />
  <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
  <PackageReference Include="RabbitMQ.Client" Version="5.2.0" />
</ItemGroup>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文