サーバーにSignalRを使用し、クライアントにAngularを使用しています...クライアントを実行すると、次のエラーが表示されます。
zone.js:2969 OPTIONS https://localhost:27967/chat/negotiate 0 ()
Utils.js:148 Error: Failed to complete negotiation with the server: Error
Utils.js:148 Error: Failed to start the connection: Error
私はそれがCORSで何かだと推測しています...私は簡単なチャットアプリケーションを実装しようとしています。 SignalRの最新バージョンを使用しています。
これは、私がフォローしているチュートリアルのコードを含むgithubです。 SignalRチャットチュートリアル
これが私のスタートアップです
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace signalrChat
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.Microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
{
builder
.AllowAnyMethod()
.AllowAnyHeader()
.WithOrigins("http://localhost:4200");
}));
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();
}
app.UseCors("CorsPolicy");
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chat");
});
}
}
}
そして、ここに私のクライアントがあります:
import { Component, OnInit } from '@angular/core';
import { HubConnection, HubConnectionBuilder } from '@aspnet/signalr';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private hubConnection: HubConnection;
nick = '';
message = '';
messages: string[] = [];
ngOnInit() {
this.nick = window.Prompt('Your name:', 'John');
this.hubConnection = new HubConnectionBuilder().withUrl('https://localhost:27967/chat').build();
this.hubConnection
.start()
.then(() => console.log("Connection Started!"))
.catch(err => console.log("Error while establishing a connection :( "));
this.hubConnection.on('sendToAll', (nick: string, receiveMessage: string) => {
const text = `${nick}: ${receiveMessage}`;
this.messages.Push(text);
})
}
public sendMessage(): void {
this.hubConnection
.invoke('sendToAll', this.nick, this.message)
.catch(err => console.log(err));
}
}
私はそれがcorsと何かであるかもしれないと思います。ありがとうございました!
編集:私はちょうどビジュアルスタジオで信号機の実装を再作成し、それが働いた。起動時に間違った設定を選択したと思います。
connection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Debug)
.withUrl("http://localhost:5000/decisionHub", {
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
})
.build();
私はよりスリムな問題に直面し、追加して修正しました
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
@Caimsが述べたようにクライアント側で。しかし、これは正しい解決策ではないと思い、ハックのように感じますか????。サーバー側にAllowCredentials
を追加する必要があります。とにかく、Azureに来るときは、その修正を中継することはできません。したがって、クライアント側でのみWSSを有効にする必要はありません。
ここに私のConfigureServicesメソッドがあります:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(o => o.AddPolicy("CorsPolicy", builder => {
builder
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.WithOrigins("http://localhost:4200");
}));
services.AddSignalR();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
これは私のConfigureメソッドです:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("CorsPolicy");
app.UseSignalR(routes =>
{
routes.MapHub<NotifyHub>("/notify");
});
app.UseMvc();
}
最後に、これがクライアント側からの接続方法です。
const connection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Debug)
.withUrl("http://localhost:5000/notify", {
//skipNegotiation: true,
//transport: signalR.HttpTransportType.WebSockets
}).build();
connection.start().then(function () {
console.log('Connected!');
}).catch(function (err) {
return console.error(err.toString());
});
connection.on("BroadcastMessage", (type: string, payload: string) => {
this.msgs.Push({ severity: type, summary: payload });
});
プロキシサーバーの設定を確認し、インターネットオプション接続タブを設定してくださいLAN設定->設定を自動的に検出し、プロキシ設定のチェックを外してください。
Azure SignalRサービスAzure Functionに接続しようとすると、Angularアプリケーションで同じ問題に直面していました。
_[FunctionName("Negotiate")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, [SignalRConnectionInfo(HubName = "broadcast")] SignalRConnectionInfo info,
ILogger log) {
log.LogInformation("Negotiate trigger function processed a request.");
return info != null ? (ActionResult) new OkObjectResult(info) : new NotFoundObjectResult("SignalR could not load");
}
_
そして、以下はAngularサービスのinit()関数コードです。
_init() {
this.getSignalRConnection().subscribe((con: any) => {
const options = {
accessTokenFactory: () => con.accessKey
};
this.hubConnection = new SignalR.HubConnectionBuilder()
.withUrl(con.url, options)
.configureLogging(SignalR.LogLevel.Information)
.build();
this.hubConnection.start().catch(error => console.error(error));
this.hubConnection.on('newData', data => {
this.mxChipData.next(data);
});
});
}
_
私の問題は_con.accessKey
_にありました。 SignalRConnectionInfo
クラスのプロパティを確認したところ、accessToken
の代わりにaccessKey
を使用する必要があることがわかりました。
_public class SignalRConnectionInfo {
public SignalRConnectionInfo();
[JsonProperty("url")]
public string Url {
get;
set;
}
[JsonProperty("accessToken")]
public string AccessToken {
get;
set;
}
}
_
そのため、コードをaccessTokenFactory: () => con.accessToken
に変更した後、すべてが正常に機能しました。
私の場合、これらすべてのものが必要というわけではなく、httpの代わりにhttpsが欠落していました。
const connection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Debug)
.withUrl('https://localhost:44308/message')
.build();
私はこれのためにほぼ2日を無駄にし、最終的に把握しました、
このエラーが発生した場合
このエラーが発生する理由
このエラーは、新しいSignalRでは古いサーバーと新しいクライアント、または新しいサーバーと古いクライアントを使用できないために発生します
つまり、.Netコアを使用してSignalRサーバーを作成する場合、.Netコアを使用してクライアントを作成する必要があります
これは私の場合の問題でした。