Utilisation de SignalR pour mon serveur et Angular pour mon client ... Lorsque j'exécute mon client, je reçois ces erreurs:
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
Je suppose que c'est quelque chose avec CORS ... J'essaie d'implémenter une application de chat simple. J'utilise la dernière version de SignalR:
Voici le github qui contient le code du tutoriel que je suis. Tutoriel SignalR Chat
Voici ma startup
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");
});
}
}
}
Et voici mon client:
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));
}
}
Je suppose que c'est peut-être quelque chose avec des cors. Je vous remercie!
EDIT: Je viens de recréer l'implémentation du signal dans Visual Studio et cela a fonctionné. Je crois que j'ai choisi les mauvais paramètres au démarrage.
connection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Debug)
.withUrl("http://localhost:5000/decisionHub", {
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
})
.build();
J'ai fait face au problème le plus mince et je l'ai résolu en ajoutant
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
côté client comme @Caims l'a mentionné. Mais je ne pense pas que ce soit la bonne solution et je me sens plus comme un hack ????. Ce que vous devez faire est d'ajouter AllowCredentials
côté serveur. Quoi qu'il en soit, lorsqu'il arrive sur Azure, vous ne pouvez pas relayer ce correctif. Il n'est donc pas nécessaire d'activer WSS uniquement côté client.
Voici ma méthode 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);
}
C'est ma méthode 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();
}
Et enfin, c'est ainsi que je me suis connecté du côté client:
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 });
});
Pouvez-vous s'il vous plaît vérifier les paramètres du serveur proxy, définir l'onglet de connexion de l'option Internet Paramètres Lan -> Sélectionnez détecter automatiquement les paramètres et décochez la configuration du proxy.
J'étais confronté au même problème dans mon Angular lorsque j'essaie de me connecter au service Azure SignalR Azure Function.
[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");
}
Et ci-dessous se trouvait mon code de fonction init () dans le service Angular.
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);
});
});
}
Mon problème était avec le con.accessKey
. Je viens de vérifier les propriétés de la classe SignalRConnectionInfo
et j'ai compris que je devais utiliser accessToken
au lieu de accessKey
.
public class SignalRConnectionInfo {
public SignalRConnectionInfo();
[JsonProperty("url")]
public string Url {
get;
set;
}
[JsonProperty("accessToken")]
public string AccessToken {
get;
set;
}
}
Donc, après avoir changé le code en accessTokenFactory: () => con.accessToken
tout a fonctionné comme d'habitude.
Dans mon cas, il n'était pas nécessaire de toutes ces choses, il me manquait le https à la place de http, et cela fonctionnait comme un charme.
const connection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Debug)
.withUrl('https://localhost:44308/message')
.build();
J'ai perdu presque deux jours pour ça et finalement compris,
Quand cette erreur se produit?
Pourquoi cette erreur se produit-elle?
L'erreur se produit car le nouveau SignalR ne vous permet pas d'utiliser l'ancien serveur et le nouveau client ou le nouveau serveur et l'ancien client
Cela signifie que si vous créez le serveur SignalR à l'aide de .Net core, vous devez créer le client à l'aide de .Net Core
C'était le problème dans mon cas.