.NET Core SignalR在IIS Express正常,部署到IIS后出现Negotiate 404错误
SignalR协商404错误排查与解决
问题现象
本地Visual Studio运行.NET Core Web应用时SignalR正常工作,发布到IIS后出现404错误:
signalr.js:1797 POST http://serverName:8080/TEST/Home/DashboardHub/negotiate?negotiateVersion=1 404 (Not Found)
signalr.js:3082 [2023-06-04T13:52:41.790Z] Error: Failed to complete negotiation with the server: Error: Not Found
核心原因分析
从错误请求路径/TEST/Home/DashboardHub/negotiate能看出,客户端请求的Hub路径被自动带上了当前页面的控制器前缀Home/,但服务端实际映射的Hub路径是根目录下的DashboardHub,导致路径不匹配。
具体解决办法
1. 修正客户端Hub路径为根相对路径
客户端代码中使用的相对路径"DashboardHub"会基于当前页面URL生成请求地址,如果当前页面在Home控制器下(比如/Home/Index),就会生成/Home/DashboardHub,和服务端的映射路径不符。
修改客户端代码,将路径改为根相对路径(以/开头):
$(() => { // 若应用部署在IIS虚拟目录TEST下,用"/TEST/DashboardHub";若为根站点,用"/DashboardHub" var connection = new signalR.HubConnectionBuilder().withUrl("/TEST/DashboardHub").build(); connection.start().then(function () { console.log("Connected..."); }); connection.on("ReceiveProducts", function () { buildProductsTable(); }) });
如果是在Razor视图中,可使用@Url.Content动态生成适配虚拟目录的路径:
var connection = new signalR.HubConnectionBuilder().withUrl("@Url.Content("~/DashboardHub")").build();
2. 检查IIS与应用池配置
- 确保服务器已安装ASP.NET Core Hosting Bundle,该组件包含IIS处理.NET Core应用所需的AspNetCoreModuleV2模块。
- 应用池的
.NET CLR版本需设置为无托管代码,因为.NET Core应用采用自托管模式,不需要IIS托管CLR。 - 确认IIS站点的物理路径指向正确的发布文件夹,且应用池权限足够访问该文件夹。
3. 验证Startup中间件顺序
确保UseRouting和UseEndpoints的顺序正确,这是SignalR路由生效的前提:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseStaticFiles(); // 必须在UseEndpoints之前调用UseRouting app.UseRouting(); // 若有认证授权中间件,需放在UseRouting之后、UseEndpoints之前 app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapHub<DashboardHub>("DashboardHub"); endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=login}/{id?}"); }); }
4. 检查发布文件与web.config配置
- 重新发布应用,选择"发布到文件夹"模式,确保所有依赖文件(包括SignalR相关dll)都被完整复制到IIS站点目录。
- 确认web.config中AspNetCore模块配置正确,示例:
<?xml version="1.0" encoding="utf-8"?> <configuration> <location path="." inheritInChildApplications="false"> <system.webServer> <handlers> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> </handlers> <aspNetCore processPath="dotnet" arguments=".\YourAppName.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" /> </system.webServer> </location> </configuration>
内容的提问来源于stack exchange,提问作者David Ash
相关产品推荐
相关产品推荐

