【问题标题】:SignalR error 404 on negotiate with asp.net application and subfolderSignalR 与 asp.net 应用程序和子文件夹协商时出现错误 404
【发布时间】:2020-11-07 04:05:18
【问题描述】:

我正在使用带有 SignalR 3.1.9 的 ASP.NET Core 3.1:

  • Microsoft.AspNetCore.SignalR.Common 3.1.9
  • Microsoft.AspNetCore.SignalR.Core 1.1.0
  • Microsoft.AspNetCore.SignalR.Protocols.Json 3.1.9

我正在使用 Javscript 客户端 v3.1.9(libman.json 文件):

    {
      "provider": "unpkg",
      "library": "@microsoft/signalr@3.1.9",
      "destination": "wwwroot/lib/signalr/",
      "files": [
        "dist/browser/signalr.js",
        "dist/browser/signalr.min.js"
      ]
    }

在我的网络服务器上,Wordpress 将根目录 (example.com) 用于前端。 Wordpress 允许请求 /core 并在 web.config 中进行一些修改,并且网站可以 100% 正确加载。

为了托管我的 .NET Core 应用程序,我创建了一个指向子文件夹 core (example.com/core) 的应用程序。我不知道这是否重要,但我所有的控制器都在“app”区域(example.com/core/app)下。

我宣布了一个新的 Hub:

    public class NotificationsHub : Hub
    {
        private readonly IMainDataService _data;
        private readonly ILogger<NotificationsHub> _logger;

        public NotificationsHub(IMainDataService data, ILoggerFactory loggerFactory)
        {
            this._data = data;
            this._logger = loggerFactory.CreateLogger<NotificationsHub>();
        }

        public async Task SendFriendNotification(Guid newFriendId, Guid currentUserId)
        {
            var currentUser = await this._data.GetUserByIdAsync(currentUserId);
            var notificationRecipientId = newFriendId.ToString();
            await Clients.User(notificationRecipientId).SendAsync("FriendRequestReceived", newFriendId, currentUserId, currentUser.FirstName, currentUser.LastName);
        }

这是我的 Startup.cs(简称为基本):

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
                options.ConsentCookie.Expiration = TimeSpan.FromDays(365);
            });

            services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAdB2C");

            services.AddControllersWithViews()
                .AddMvcLocalization()
                .AddMicrosoftIdentityUI();

            services.AddRazorPages();
            services.AddSignalR();
            services.AddRouting();

            services.AddOptions();

            services.Configure<OpenIdConnectOptions>(Configuration.GetSection("AzureAdB2C"));

            services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

            services.AddDistributedMemoryCache();

            services.AddSession(options =>
            {
                options.Cookie.IsEssential = true;
            });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            // ...

            if ((env.IsDevelopment() || env.IsStaging() || env.IsProduction()) && !env.IsEnvironment("Localhost"))
            {
                app.UsePathBase("/core");
            }

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();

                endpoints.MapControllerRoute(
                    name: "areas",
                    pattern: "{area:exists}/{controller=Map}/{action=Index}/{id?}"
                );
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{area=App}/{controller=Map}/{action=Index}"
                );
                endpoints.MapControllerRoute(
                    name: "profile",
                    pattern: "{area=App}/{controller=Profile}/{action=Index}/{id?}"
                );

                endpoints.MapRazorPages();

                endpoints.MapDbLocalizationAdminUI();
                endpoints.MapDbLocalizationClientsideProvider();

                if (env.EnvironmentName == "Localhost")
                {
                    endpoints.MapHub<NotificationsHub>("/notificationshub");
                }
                else
                {
                    endpoints.MapHub<NotificationsHub>("/core/notificationshub");
                }
            });
        }

在本地,因为我直接在根目录运行我的 .NET Core 应用程序,所以没有问题。但是当我部署到使用子文件夹 /core 的 Dev/Staging/Prod 时,我总是在以下 URL 上收到错误 404:https://www.example.com/core/notificationshub/negotiate?negotiateVersion=1

我也试过了:

在这两种情况下,我都会收到 404 异常。在 F12 控制台中,404 后面总是跟以下行:

Error: Failed to complete negotiation with the server: Error: Not Found
Error: Failed to start the connection: Error: Not Found
Error: Not Found

上面的第 3 行指向我的 JavaScript 客户端:

"use strict";

var currentUrl = window.location.href;

var basePath = '';
if (currentUrl.includes("/core") == true) {
    basePath = '/core'
}

var connection = new signalR.HubConnectionBuilder().withUrl(basePath + "/notificationshub").build();

connection.start().catch(function (err) {
    return console.error(err.toString());
});

错误就在线connection.start()上。

我尝试在路径前用 ../ 修改上一行,但没有帮助:

let connection = new signalR.HubConnectionBuilder().withUrl("../" + basePath + "/notificationshub").build();

知道我是否遗漏了什么?让 SignalR 处理根 URL 似乎很简单,但如果有子文件夹,则不然。

【问题讨论】:

  • 看起来您正在将您的应用映射到“/core”,然后将您的集线器映射到“/core/hub”。所以你的中心实际上是在“/core/core/hub”。
  • 你就是@Brennan,我完全错过了(捂脸)!您是否有机会添加答案以便我将其标记为答案?
  • "Microsoft.AspNetCore.SignalR.Core" 是旧的 .net core 2.x 包,删除它
  • 感谢@magicandre1981 的信息!是否需要更换或仅其他 2 个就足够了?
  • 另外两行就够了。

标签: c# signalr asp.net-core-3.1 signalr.client asp.net-core-signalr


【解决方案1】:

您似乎正在将您的应用映射到“/core”,然后将您的中心映射到“/core/hub”。所以你的中心实际上是在“/core/core/hub”。

【讨论】:

  • 因此,通过使用app.UsePathBase("/core");,然后使用endpoints.MapHub&lt;NotificationsHub&gt;("/notificationshub");(开头没有/core),我可以在example.com/core 上使用我的Hub。在这里我的客户let connection = new signalR.HubConnectionBuilder().withUrl(basePath + "/notificationshub").build(); 发帖以防万一它可能对遇到类似问题的人有所帮助!
猜你喜欢
  • 2016-09-25
  • 2013-11-23
  • 1970-01-01
  • 2016-12-23
  • 1970-01-01
  • 2018-04-18
  • 2021-03-11
  • 1970-01-01
  • 2015-10-28
相关资源
最近更新 更多