c# - websocket握手期间的asp.net核心信号器错误
问题描述
对不起,我的英语不好。我正在尝试从 SPA 应用程序(Vue.JS)连接到 SignalR Hub。
来自客户端的代码:
this.hubConnection = new HubConnectionBuilder()
.withUrl('http://localhost:*****/testhub')
.configureLogging(LogLevel.Information)
.build()
我收到一个错误:错误:无法完成与服务器的协商:SyntaxError: Unexpected token < in JSON at position 0
然后我尝试了:
this.hubConnection = new HubConnectionBuilder()
.withUrl('http://localhost:*****/testhub', {
skipNegotiation: true,
transport: HttpTransportType.WebSockets
})
.configureLogging(LogLevel.Information)
.build()
没有任何改变(但我得到另一个错误):
WebSocket 连接到“ws://localhost:50523/testhub”失败:WebSocket 握手期间出错:意外响应代码:200
我在 Startup.cs 中检查了 UseWebsockets。我也尝试在客户端更改 SignalR 版本,但无法解决问题。当我尝试在多页应用程序中连接 SignalR 时,我看不到它。我第一次拥有它。
我做错了什么?
启动.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.SpaServices.Webpack;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.WebSockets;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authorization;
using Newtonsoft.Json;
using Vue2Spa.Models;
using Vue2Spa.Controllers.App;
using Vue2Spa.Hubs;
namespace Vue2Spa
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore)
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
var connection = @"Server=.\SQLEXPRESS;Database=****;Trusted_Connection=True;";
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connection));
services.AddIdentity<Account, IdentityRole>(options =>
options.SignIn.RequireConfirmedEmail = true)
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<ApplicationDbContext>();
//JWT
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = AuthOptions.ISSUER,
ValidateAudience = true,
ValidAudience = AuthOptions.AUDIENCE,
ValidateLifetime = true,
IssuerSigningKey = AuthOptions.GetSymmetricSecurityKey(),
ValidateIssuerSigningKey = true,
};
})
services.AddAuthorization(options =>
{
});
/*services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser()
.Build();
});*/
// Simple example with dependency injection for a data provider.
services.AddSingleton<Providers.IWeatherProvider, Providers.WeatherProviderFake>();
//File's parameters
services.Configure<FormOptions>(o => {
o.ValueLengthLimit = int.MaxValue;
o.MultipartBodyLengthLimit = int.MaxValue;
o.MemoryBufferThreshold = int.MaxValue;
});
services.AddSignalR();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
// Webpack initialization with hot-reload.
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true,
});
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "default1",
template: "{controller=Admin}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
routes.MapSpaFallbackRoute(
name: "spa-fallback1",
defaults: new { controller = "Admin", action = "Index" });
});
app.UseAuthentication();
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Xss-Protection", "1");
await next();
}).UseSignalR(route =>
{
route.MapHub<ChatHub>("/chat");
});
}
}
}
解决方案
问题解决了。我将 UseSignalR 移到了 UseMvc 之上。
推荐阅读
- kubernetes - Kubernetes | 推出撤消与部署到旧版本有什么区别?
- logging - 如何在身份验证期间创建系统日志?
- python - Trying to grab location of job postings on website using python
- git - 我尝试拉一个远程分支。错误:致命:无法锁定参考
- swift - Swift 泛型和枚举作为数据源
- python - 比较两个数据框并根据多个条件删除行
- angular - Angular 中的笑话问题 - UnhandledPromiseRejectionWarning zone.js
- angular - 错误:未找到 [组件名称] 的组件工厂。你把它添加到@NgModule.entryComponents 了吗?
- python-3.x - 在 Python 中读入多个文件并将它们一个一个保存在不同的目录中
- php - 使用 PHP 解析高度复杂的 XML 文件