Usando SignalR para mi servidor y Angular para mi cliente... Cuando ejecuto mi cliente recibo estos errores:
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: ErrorSupongo que es algo con CORS... Estoy tratando de implementar una aplicación de chat simple. Estoy usando la última versión de SignalR:
Aquí está el github que contiene el código para el tutorial que estoy siguiendo. Tutorial de chat de SignalR
Aquí está mi inicio
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"); }); } } }Y aquí está mi cliente:
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)); } }Supongo que puede ser algo con cors. ¡Gracias!
EDITAR: acabo de recrear la implementación del señalizador en Visual Studio y funcionó. Creo que elegí la configuración incorrecta al iniciar.
En mi caso no era necesario todo eso, me faltaba el https en lugar del http, y funcionó a las mil maravillas.
const connection = new signalR.HubConnectionBuilder() .configureLogging(signalR.LogLevel.Debug) .withUrl('https://localhost:44308/message') .build();Perdí casi dos días para esto y finalmente me di cuenta,
¿Cuándo ocurre este error?
¿Por qué se produce este error?
El error ocurre porque el nuevo SignalR no le permite usar el servidor anterior y el cliente nuevo o el servidor nuevo y el cliente anterior
Significa que si crea el servidor SignalR usando .Net Core, entonces debe crear el cliente usando .Net Core
Este fue el problema en mi caso.
Yo tuve el mismo problema, y resulta que el launchSettings.json en la parte donde dice signalRchatServer no hace nada, la url que me funciono fue la del iisexpress, lo digo porque hay muchos lugares donde dicen que el url es el de abajo.
Enfrenté el problema más viscoso y lo solucioné agregando
skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets en el lado del cliente como mencionó @Caims. Pero no creo que esta sea la solución correcta y me siento más como un truco 😊. Lo que tiene que hacer es agregar AllowCredentials en el lado del servidor. De todos modos, cuando se trata de Azure, no puedes confiar en esa solución. Por lo tanto, no es necesario habilitar WSS solo en el lado del cliente.
Aquí está mi método 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); }Este es mi método Configurar :
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseCors("CorsPolicy"); app.UseSignalR(routes => { routes.MapHub<NotifyHub>("/notify"); }); app.UseMvc(); }Y finalmente así es como me conecté desde el lado del cliente:
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 }); });Estaba enfrentando el mismo problema en mi aplicación Angular cuando intento conectarme al servicio 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"); }Y debajo estaba mi código de función init() en el servicio 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); }); }); } Mi problema fue con con.accessKey . Acabo de verificar las propiedades de la clase SignalRConnectionInfo y entendí que necesito usar accessToken en lugar de accessKey .
public class SignalRConnectionInfo { public SignalRConnectionInfo(); [JsonProperty("url")] public string Url { get; set; } [JsonProperty("accessToken")] public string AccessToken { get; set; } } Entonces, después de cambiar el código a accessTokenFactory: () => con.accessToken todo funcionó como de costumbre.
connection = new signalR.HubConnectionBuilder() .configureLogging(signalR.LogLevel.Debug) .withUrl("http://localhost:5000/decisionHub", { skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets }) .build();Estaba apuntando al punto final equivocado. yo estaba usando
https://localhost:5001/api/message-hub en lugar de
https://localhost:5001/message-hub (extra/api)
Además, si está utilizando Angular, es probable que obtenga un error de Websocket no ABIERTO justo después de corregir este, así que aquí hay un enlace para evitar más búsquedas.
Tuve el mismo error debido al origen cruzado. Esto me lo resolvió program.cs (dotnet 6) o startup.cs (dotnetcore <6)
app.UseCors(builder => builder .AllowAnyHeader() .AllowAnyMethod() .SetIsOriginAllowed(_ => true) .AllowCredentials() );Tenga en cuenta que no debe abrir todos los orígenes si no es un entorno de desarrollo o casos especiales.