- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个使用 signalR 的 Angular 应用程序。它托管在 .NET Core 3.1 应用程序中。升级到 Angular 9 后,signalR 不再有效。在 Angular 8 中一切正常。自更新以来,我一直收到类似的错误
404 Error: Failed to complete negotiation with the server
Failed to start the connection
package.json
文件我有以下包:
"@microsoft/signalr": "3.1.2",
"@microsoft/signalr-protocol-msgpack":"3.1.2"
在 .NET 核心我有包:
Microsoft.AspNetCore.SignalR.Common 3.1.2 Microsoft.AspNetCore.SignalR.Protocols.MessagePack 3.1.2
我使用的 Typescript 版本是 v3.7.5。我启用了 SSL。
{
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
}
不幸的是,两者都不起作用。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Server.IISIntegration;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using System.IO;
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public static IConfiguration Configuration
{
get; set;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AppConfig>(options =>
{
Configuration.GetSection("AppConfig").Bind(options);
});
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
services.AddSignalR(o =>
{
o.EnableDetailedErrors = true;
o.MaximumReceiveMessageSize = 1000000;
}).AddMessagePackProtocol();
services.AddControllersWithViews()
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
options.JsonSerializerOptions.DictionaryKeyPolicy = null;
});
services.AddRazorPages();
}
// 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.UseHttpContext();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), @"Uploads")),
RequestPath = new PathString("/Uploads")
});
app.Use(async (context, next) =>
{
context.Response.Headers.Remove("X-XSS-Protection");
context.Response.Headers.Add("X-Xss-Protection", "1");
context.Response.Headers.Remove("X-Frame-Options");
context.Response.Headers.Add("X-Frame-Options", "DENY");
context.Response.Headers.Remove("Referrer-Policy");
context.Response.Headers.Add("Referrer-Policy", "no-referrer");
context.Response.Headers.Remove("X-Content-Type-Options");
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
//context.Response.Headers.Remove("Content-Security-Policy");
//context.Response.Headers.Add(
// "Content-Security-Policy",
// "default-src 'self'; " +
// "img-src 'self' myblobacc.blob.core.windows.net; " +
// "font-src 'self'; " +
// "style-src 'self'; " +
// "script-src 'self' 'nonce-KIBdfgEKjb34ueiw567bfkshbvfi4KhtIUE3IWF' 'nonce-rewgljnOIBU3iu2btli4tbllwwe'; " +
// "frame-src 'self';" +
// "connect-src 'self';");
await next();
});
if(!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
app.UseRouting();
app.UseAuthentication();
WebSocketOptions webSocketOptions = new WebSocketOptions();
webSocketOptions.AllowedOrigins.Add("*");
app.UseWebSockets(webSocketOptions);
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<AppHub>("/appHub");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if(env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
app.UseCookiePolicy();
}
}
我的 Angular 信号R服务:
import { Location } from '@angular/common';
import { EventEmitter, Injectable, OnDestroy } from '@angular/core';
import { HubConnection, HubConnectionBuilder, HubConnectionState, IHubProtocol, LogLevel } from '@microsoft/signalr';
import { MessagePackHubProtocol } from '@microsoft/signalr-protocol-msgpack';
import { Subscription } from 'rxjs';
@Injectable()
export class AppSignalRService implements OnDestroy
{
public connectionEstablished = new EventEmitter<Boolean>();
public startConnectionTimeoutDelay: number = 3000;
public protocol: IHubProtocol = new MessagePackHubProtocol();
public autoReconnect: boolean = true;
private _userId: number = 0;
private _connectionIsEstablished: boolean = false;
private _hubConnection: HubConnection;
private connectedSubscription: Subscription;
constructor(public location: Location)
{
}
createConnection(huburl: string, userId: number)
{
this._userId = userId;
if (!this._hubConnection && this._userId > 0)
{
let hubConnectionBuilder: HubConnectionBuilder = new HubConnectionBuilder();
hubConnectionBuilder.withUrl(this.location.path.name + huburl);
hubConnectionBuilder.withHubProtocol(this.protocol);
hubConnectionBuilder.configureLogging(LogLevel.Information);
if (this.autoReconnect)
{
hubConnectionBuilder.withAutomaticReconnect([0, 1000, 1000, 1000, 1000, 1000, 2000, 5000, 10000, 20000, 30000, null]);
}
this._hubConnection = hubConnectionBuilder.build();
this.hubConnection.onclose((msg) =>
{
console.log(msg.message);
this.startConnection();
});
this.hubConnection.onreconnected((connectionId: string) =>
{
this.hubConnection.invoke("RegisterConnection", this._userId)
});
}
}
startConnection()
{
if (this._hubConnection.state == HubConnectionState.Disconnected)
{
this._hubConnection
.start()
.then(() =>
{
this._connectionIsEstablished = true;
console.log('Hub connection started');
this.connectionEstablished.emit(true);
this.hubConnection.invoke("RegisterConnection", this._userId);
})
.catch(err =>
{
this._connectionIsEstablished = false;
console.log('Error while establishing connection, retrying...');
setTimeout(() =>
{
this.startConnection();
}, this.startConnectionTimeoutDelay);
});
}
}
// ...args: any[] allows you to pass any number of arguments
run(method: string, ...args: any[])
{
switch (this.hubConnection.state)
{
case HubConnectionState.Connected: ;
this.hubConnection.invoke(method, ...args);
break;
case HubConnectionState.Connecting:
this.connectedSubscription = this.connectionEstablished.subscribe((data: any) =>
{
this.hubConnection.invoke(method, ...args);
this.connectedSubscription.unsubscribe();
});
break;
default:
this.hubConnection.start()
.then(() =>
{
this.hubConnection.invoke(method, args)
this.hubConnection.invoke("RegisterConnection", this._userId);
})
.catch(err => console.error(err.toString()));
break;
}
}
get connectionIsEstablished(): boolean
{
return this._connectionIsEstablished;
}
get hubConnection(): HubConnection
{
return this._hubConnection;
}
ngOnDestroy()
{
if (this.connectedSubscription)
{
// prevent memory leak when component destroyed
this.connectedSubscription.unsubscribe();
}
}
}
{
"name": "mic",
"private": true,
"version": "1.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve --live-reload=false",
"build": "ng build",
"build:ssr": "ng run MIC:server:dev",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"postcss": {},
"dependencies": {
"@angular/animations": "9.0.2",
"@angular/cdk": "9.0.1",
"@angular/common": "9.0.2",
"@angular/compiler": "9.0.2",
"@angular/core": "9.0.2",
"@angular/flex-layout": "9.0.0-beta.29",
"@angular/forms": "9.0.2",
"@angular/localize": "9.0.2",
"@angular/material": "9.0.1",
"@angular/material-moment-adapter": "9.0.1",
"@angular/platform-browser": "9.0.2",
"@angular/platform-browser-dynamic": "9.0.2",
"@angular/platform-server": "9.0.2",
"@angular/router": "9.0.2",
"@angular-devkit/schematics": "9.0.3",
"@fortawesome/angular-fontawesome": "0.6.0",
"@fortawesome/fontawesome-svg-core": "1.2.27",
"@fortawesome/free-regular-svg-icons": "5.12.1",
"@fortawesome/free-solid-svg-icons": "5.12.1",
"@microsoft/signalr": "3.1.2",
"@microsoft/signalr-protocol-msgpack": "3.1.2",
"@ng-bootstrap/ng-bootstrap": "6.0.0",
"@ngmodule/material-carousel": "0.6.0",
"@ng-select/ng-select": "3.7.2",
"@nguniversal/module-map-ngfactory-loader": "9.0.0-next.9",
"@swimlane/ngx-charts": "13.0.2",
"angular2-notifications": "3.0.0",
"angular-dual-listbox": "5.0.1",
"aspnet-prerendering": "^3.0.1",
"bootstrap": "4.4.1",
"classlist.js": "1.1.20150312",
"core-js": "3.6.4",
"date-fns": "2.9.0",
"hammerjs": "2.0.8",
"hammer-timejs": "1.1.0",
"hash-sum": "2.0.0",
"immutable": "4.0.0-rc.12",
"intl": "1.2.5",
"jquery": "3.4.1",
"jwt-decode": "2.2.0",
"material-design-icons": "3.0.1",
"moment": "^2.24.0",
"ng-validator": "2.0.0",
"ngx-material-timepicker": "^5.3.0",
"oidc-client": "1.10.1",
"popper.js": "1.16.1",
"primeicons": "2.0.0",
"primeng": "9.0.0-rc.4",
"rxjs": "6.5.4",
"tippy.js": "5.2.1",
"tslib": "^1.10.0",
"web-animations-js": "^2.3.2",
"zone.js": "0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "0.900.3",
"@angular/cli": "9.0.3",
"@angular/compiler-cli": "9.0.2",
"@angular/language-service": "9.0.2",
"@intervolga/optimize-cssnano-plugin": "1.0.6",
"@types/jasmine": "3.5.3",
"@types/jasminewd2": "2.0.8",
"@types/jwt-decode": "2.2.1",
"@types/node": "13.7.4",
"autoprefixer": "9.7.4",
"codelyzer": "5.2.1",
"jasmine-core": "3.5.0",
"jasmine-spec-reporter": "4.2.1",
"karma": "4.4.1",
"karma-chrome-launcher": "3.1.0",
"karma-coverage-istanbul-reporter": "2.1.1",
"karma-jasmine": "3.1.1",
"karma-jasmine-html-reporter": "1.5.2",
"karma-scss-preprocessor": "4.0.0",
"typescript": "3.7.5"
},
"optionalDependencies": {
"node-sass": "4.13.1",
"protractor": "6.0.0",
"tslint": "6.0.0",
"ts-node": "8.6.2"
}
}
最佳答案
我设法找到了问题所在并让 signalR 再次工作。在我的 tsconfig.json 文件中,“compilerOptions”部分有以下值:
"target": "es2015"
target": "es5"
关于angular - 由于升级到 Angular 9 Signalr 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60357035/
我正在尝试在项目中学习和添加 Angular 国际化。我只能理解 Angular 文档 (https://angular.io/guide/i18n-overview) 的编译时翻译。 我需要这样的东
在我的 Angular 应用程序中,基于登录用户,我想通过显示/隐藏不同的菜单项或允许/禁止某些路由来授予或限制功能。 目前成功登录后,我的 .NET Core API 会返回一个 JWT token
我是 Angular 的新手,目前我已经看过 angular.io 网站提供的一些示例。但是在component decorator在文档中的解释,它指出 Angular components are
这里是service employee-service.service.ts的代码 import { Injectable } from '@angular/core'; import { HttpC
我目前正在使用@angular/http URLSearchParams 类来检索 URL 参数。在 Angular 5 中,注意到这已被弃用,但我没有看到以我当前使用的方式替换 URLSearchP
我目前正在使用@angular/http URLSearchParams 类来检索 URL 参数。在 Angular 5 中,注意到这已被弃用,但我没有看到以我当前使用的方式替换 URLSearchP
如何正确安装 PUG/JADE 到 Angular 2 或更高版本 这样在工作和 AOT 和 JiT 的同时 工作单元和集成测试 并且在创建每个新组件时不会受到太多影响 最佳答案 我看到了很多解决方案
我的 Angular 12 应用程序中有一些通用组件,我计划将其创建为一个 Angular 库,以便其他应用程序也可以使用它。我们有一些应用程序在较低版本的 angular(例如 angular 8/
tl;dr; ng build 删除了包含我编译的自定义库的/dist 文件夹。这会使我项目代码中对该库的所有引用无效,从而导致 ng build 最终失败。我做错了什么? 我关注了documenta
我正在将一些“遗留”(非 typescript )js 库导入到我的 Angular SPA 中。 通常我只是从 cdn 添加一个负载到 index.html 就像: 在 Angular 分量中我只
我有这个 angular 应用程序,它基本上使用了库的概念。 我有 2 个名为 的库Lib1 和 lib2 根据他们所服务的微服务分组。 现在我将这些库导入主应用程序,即 应用1 事情一直到现在。 现
我在我的项目中启用了 angular Universal。我现在想完全删除它。我试图删除以下文件 /server.ts /webpack.server.config.js /src/tsconfig.
我已经有一个 AuthService 在登录时对用户进行身份验证,并且 AuthGuard 在未登录的情况下阻止访问。 某些页面我通过 UserProfile/Role 限制访问,但现在我需要阻止页面
我正在尝试使用 angular、TypeORM、SQLite 和其他组件作为 webpack 构建 Electron 应用程序。 我从在 GitHub 上找到的示例开始我的开发:https://git
我在从 Angular 8 更新到 9 并运行时遇到以下错误 ng 更新@angular/material: Package "@angular/flex-layout" has an incompa
我正在尝试使用 Angular 9,我想创建一个项目,然后创建一个库项目并开始向其中添加我想稍后在 GitHub 上发布的通用模块,并在我的本地使用这些库项目。 相关依赖如下: Angular CLI
我正在尝试使用 Angular 9,我想创建一个项目,然后创建一个库项目并开始向其中添加我想稍后在 GitHub 上发布的通用模块,并在我的本地使用这些库项目。 相关依赖如下: Angular CLI
我正在我的 h1 元素“之前”创建一个小的程式化三 Angular 形图案,但我无法正确地圆 Angular 。右上角没问题,但其他两个有剪裁问题。 这是输出以及形状的放大图像: 使用的代码如下: h
我有一个 Angular 元素,带有自定义标记名 - fancy-button。如何将 fancy-button 嵌入 Angular 应用程序? 我已经尝试了以下方法,但都没有用 - 在 index
我已将我的项目从 angular 5.2.9 升级到 angular 6.0.0-rc.5。 除了包路径中的几个快速 RxJS 修复外,一切看起来都不错。(此链接非常有用:Want to upgrad
我是一名优秀的程序员,十分优秀!