Cliente de ASP.NET Core SignalR JavaScriptASP.NET Core SignalR JavaScript client

Por Rachel AppelBy Rachel Appel

La biblioteca de cliente de ASP.NET Core SignalR JavaScript permite a los desarrolladores llamar a código de concentrador de servidor.The ASP.NET Core SignalR JavaScript client library enables developers to call server-side hub code.

Vea o descargue el código de ejemplo (cómo descargarlo)View or download sample code (how to download)

Instalar el SignalR paquete de clienteInstall the SignalR client package

La SignalR biblioteca de cliente de JavaScript se entrega como un paquete NPM .The SignalR JavaScript client library is delivered as an npm package. En las secciones siguientes se describen diferentes formas de instalar la biblioteca de cliente de.The following sections outline different ways to install the client library.

Instalación con NPMInstall with npm

En Visual Studio, ejecute los siguientes comandos desde la consola del administrador de paquetes en la carpeta raíz.For Visual Studio, run the following commands from Package Manager Console while in the root folder. Para Visual Studio Code, ejecute los siguientes comandos desde el terminal integrado .For Visual Studio Code, run the following commands from the Integrated Terminal .

npm init -y
npm install @microsoft/signalr

NPM instala el contenido del paquete en la carpeta \ @microsoft\signalr\dist\browser node_modules .npm installs the package contents in the node_modules\@microsoft\signalr\dist\browser folder. Cree una nueva carpeta denominada signalr en la carpeta wwwroot \ lib .Create a new folder named signalr under the wwwroot\lib folder. Copie el archivo de signalr.js en la carpeta wwwroot\lib\signalr .Copy the signalr.js file to the wwwroot\lib\signalr folder.

Haga referencia al SignalR cliente de JavaScript en el <script> elemento.Reference the SignalR JavaScript client in the <script> element. Por ejemplo:For example:

<script src="~/lib/signalr/signalr.js"></script>

Uso de una Content Delivery Network (CDN)Use a Content Delivery Network (CDN)

Para usar la biblioteca de cliente sin el requisito previo de NPM, haga referencia a una copia hospedada en CDN de la biblioteca de cliente.To use the client library without the npm prerequisite, reference a CDN-hosted copy of the client library. Por ejemplo:For example:

<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.min.js"></script>

La biblioteca de cliente está disponible en las siguientes redes CDN:The client library is available on the following CDNs:

Instalación con LibManInstall with LibMan

LibMan se puede usar para instalar archivos de biblioteca de cliente específicos desde la biblioteca de cliente hospedada en CDN.LibMan can be used to install specific client library files from the CDN-hosted client library. Por ejemplo, agregue solo el archivo JavaScript reducida al proyecto.For example, only add the minified JavaScript file to the project. Para obtener más información sobre este enfoque, consulte Agregar la SignalR biblioteca de cliente.For details on that approach, see Add the SignalR client library.

Conexión a un concentradorConnect to a hub

El código siguiente crea e inicia una conexión.The following code creates and starts a connection. El nombre del centro no distingue mayúsculas de minúsculas:The hub's name is case insensitive:

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .configureLogging(signalR.LogLevel.Information)
    .build();

async function start() {
    try {
        await connection.start();
        console.log("SignalR Connected.");
    } catch (err) {
        console.log(err);
        setTimeout(start, 5000);
    }
};

connection.onclose(start);

// Start the connection.
start();

Conexiones entre orígenesCross-origin connections

Normalmente, los exploradores cargan conexiones desde el mismo dominio que la página solicitada.Typically, browsers load connections from the same domain as the requested page. Sin embargo, hay ocasiones en las que se requiere una conexión a otro dominio.However, there are occasions when a connection to another domain is required.

Importante

El código de cliente debe usar una dirección URL absoluta en lugar de una dirección URL relativa.The client code must use an absolute URL instead of a relative URL. Cambio de .withUrl("/chathub") a .withUrl("https://myappurl/chathub").Change .withUrl("/chathub") to .withUrl("https://myappurl/chathub").

Para evitar que un sitio malintencionado Lea datos confidenciales de otro sitio, las conexiones entre orígenes están deshabilitadas de forma predeterminada.To prevent a malicious site from reading sensitive data from another site, cross-origin connections are disabled by default. Para permitir una solicitud entre orígenes, habilítela en la Startup clase:To allow a cross-origin request, enable it in the Startup class:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SignalRChat.Hubs;

namespace SignalRChat
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddSignalR();

            services.AddCors(options =>
            {
                options.AddDefaultPolicy(builder =>
                {
                    builder.WithOrigins("https://example.com")
                        .AllowCredentials();
                });
            });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();
            app.UseRouting();

            app.UseCors();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapHub<ChatHub>("/chathub");
            });
        }
    }
}

Llamar a métodos de Hub desde el clienteCall hub methods from the client

Los clientes de JavaScript llaman a métodos públicos en los concentradores a través del método Invoke de HubConnection.JavaScript clients call public methods on hubs via the invoke method of the HubConnection. El invoke método acepta:The invoke method accepts:

  • Nombre del método de concentrador.The name of the hub method.
  • Cualquier argumento definido en el método de concentrador.Any arguments defined in the hub method.

En el ejemplo siguiente, el nombre del método en el concentrador es SendMessage .In the following example, the method name on the hub is SendMessage. Los argumentos segundo y tercero pasados a invoke la asignación a los argumentos y del método del concentrador user message :The second and third arguments passed to invoke map to the hub method's user and message arguments:

try {
    await connection.invoke("SendMessage", user, message);
} catch (err) {
    console.error(err);
}

Nota

La llamada a métodos de concentrador desde un cliente solo se admite cuando se usa el SignalR servicio de Azure en el modo predeterminado .Calling hub methods from a client is only supported when using the Azure SignalR Service in Default mode. Para obtener más información, consulte preguntas más frecuentes (repositorio de github de Azure signalr).For more information, see Frequently Asked Questions (azure-signalr GitHub repository).

El invoke método devuelve un compromisode JavaScript.The invoke method returns a JavaScript Promise. PromiseSe resuelve con el valor devuelto (si existe) cuando el método en el servidor devuelve.The Promise is resolved with the return value (if any) when the method on the server returns. Si el método en el servidor produce un error, Promise se rechaza con el mensaje de error.If the method on the server throws an error, the Promise is rejected with the error message. Use async y await o los Promise then métodos y de catch para controlar estos casos.Use async and await or the Promise's then and catch methods to handle these cases.

Los clientes de JavaScript también pueden llamar a métodos públicos en los concentradores a través del método send de HubConnection .JavaScript clients can also call public methods on hubs via the the send method of the HubConnection. A diferencia del invoke método, el send método no espera una respuesta del servidor.Unlike the invoke method, the send method doesn't wait for a response from the server. El send método devuelve un JavaScript Promise .The send method returns a JavaScript Promise. PromiseSe resuelve cuando el mensaje se ha enviado al servidor.The Promise is resolved when the message has been sent to the server. Si se produce un error al enviar el mensaje, Promise se rechaza con el mensaje de error.If there is an error sending the message, the Promise is rejected with the error message. Use async y await o los Promise then métodos y de catch para controlar estos casos.Use async and await or the Promise's then and catch methods to handle these cases.

Nota

El uso de send no espera hasta que el servidor haya recibido el mensaje.Using send doesn't wait until the server has received the message. Por lo tanto, no es posible devolver datos ni errores del servidor.Consequently, it's not possible to return data or errors from the server.

Llamar a métodos de cliente desde el concentradorCall client methods from the hub

Para recibir mensajes desde el concentrador, defina un método mediante el método on de la HubConnection .To receive messages from the hub, define a method using the on method of the HubConnection.

  • Nombre del método de cliente JavaScript.The name of the JavaScript client method.
  • Argumentos que el concentrador pasa al método.Arguments the hub passes to the method.

En el ejemplo siguiente, el nombre del método es ReceiveMessage .In the following example, the method name is ReceiveMessage. Los nombres de argumento son user y message :The argument names are user and message:

connection.on("ReceiveMessage", (user, message) => {
    const li = document.createElement("li");
    li.textContent = `${user}: ${message}`;
    document.getElementById("messageList").appendChild(li);
});

El código anterior en connection.on se ejecuta cuando el código del lado servidor lo llama mediante el SendAsync método:The preceding code in connection.on runs when server-side code calls it using the SendAsync method:

public async Task SendMessage(string user, string message)
{
    await Clients.All.SendAsync("ReceiveMessage", user, message);
}

SignalR determina el método de cliente al que se debe llamar haciendo coincidir el nombre del método y los argumentos definidos en SendAsync y connection.on .SignalR determines which client method to call by matching the method name and arguments defined in SendAsync and connection.on.

Nota

Como procedimiento recomendado, llame al método Start en el HubConnection después de on .As a best practice, call the start method on the HubConnection after on. Esto garantiza que los controladores se registren antes de que se reciban los mensajes.Doing so ensures your handlers are registered before any messages are received.

Registro y control de erroresError handling and logging

Use try y catch con async y, await o Promise el catch método de para controlar los errores del lado cliente.Use try and catch with async and await or the Promise's catch method to handle client-side errors. Use console.error para generar errores en la consola del explorador:Use console.error to output errors to the browser's console:

try {
    await connection.invoke("SendMessage", user, message);
} catch (err) {
    console.error(err);
}

Configure el seguimiento del registro del lado cliente pasando un registrador y un tipo de evento al registro cuando se establezca la conexión.Set up client-side log tracing by passing a logger and type of event to log when the connection is made. Los mensajes se registran con el nivel de registro especificado y superior.Messages are logged with the specified log level and higher. Los niveles de registro disponibles son los siguientes:Available log levels are as follows:

  • signalR.LogLevel.Error: Mensajes de error.signalR.LogLevel.Error: Error messages. ErrorSolo registra mensajes.Logs Error messages only.
  • signalR.LogLevel.Warning: Mensajes de advertencia sobre posibles errores.signalR.LogLevel.Warning: Warning messages about potential errors. Registros Warning y Error mensajes.Logs Warning, and Error messages.
  • signalR.LogLevel.Information: Mensajes de estado sin errores.signalR.LogLevel.Information: Status messages without errors. Registra Information Warning mensajes, y Error .Logs Information, Warning, and Error messages.
  • signalR.LogLevel.Trace: Mensajes de seguimiento.signalR.LogLevel.Trace: Trace messages. Registra todo, incluidos los datos transportados entre el concentrador y el cliente.Logs everything, including data transported between hub and client.

Use el método configureLogging en HubConnectionBuilder para configurar el nivel de registro.Use the configureLogging method on HubConnectionBuilder to configure the log level. Los mensajes se registran en la consola del explorador:Messages are logged to the browser console:

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .configureLogging(signalR.LogLevel.Information)
    .build();

Volver a conectar clientesReconnect clients

Volver a conectar automáticamenteAutomatically reconnect

El cliente de JavaScript para SignalR puede configurarse para que se vuelva a conectar automáticamente mediante el withAutomaticReconnect método en HubConnectionBuilder.The JavaScript client for SignalR can be configured to automatically reconnect using the withAutomaticReconnect method on HubConnectionBuilder. No se volverá a conectar automáticamente de forma predeterminada.It won't automatically reconnect by default.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withAutomaticReconnect()
    .build();

Sin parámetros, withAutomaticReconnect() configura el cliente para que espere 0, 2, 10 y 30 segundos, respectivamente, antes de intentar cada intento de reconexión, deteniéndose después de cuatro intentos erróneos.Without any parameters, withAutomaticReconnect() configures the client to wait 0, 2, 10, and 30 seconds respectively before trying each reconnect attempt, stopping after four failed attempts.

Antes de iniciar cualquier intento de reconexión, HubConnection cambiará al HubConnectionState.Reconnecting Estado de y activará sus onreconnecting devoluciones de llamada en lugar de pasar al Disconnected Estado y desencadenar sus onclose devoluciones de llamada como una HubConnection sin reconexión automática configurada.Before starting any reconnect attempts, the HubConnection will transition to the HubConnectionState.Reconnecting state and fire its onreconnecting callbacks instead of transitioning to the Disconnected state and triggering its onclose callbacks like a HubConnection without automatic reconnect configured. Esto proporciona una oportunidad para advertir a los usuarios de que se ha perdido la conexión y deshabilitar los elementos de la interfaz de usuario.This provides an opportunity to warn users that the connection has been lost and to disable UI elements.

connection.onreconnecting(error => {
    console.assert(connection.state === signalR.HubConnectionState.Reconnecting);

    document.getElementById("messageInput").disabled = true;

    const li = document.createElement("li");
    li.textContent = `Connection lost due to error "${error}". Reconnecting.`;
    document.getElementById("messagesList").appendChild(li);
});

Si el cliente se vuelve a conectar correctamente dentro de los cuatro primeros intentos, HubConnection volverá a pasar al Connected Estado y activará sus onreconnected devoluciones de llamada.If the client successfully reconnects within its first four attempts, the HubConnection will transition back to the Connected state and fire its onreconnected callbacks. Esto proporciona una oportunidad para informar a los usuarios de que se ha restablecido la conexión.This provides an opportunity to inform users the connection has been reestablished.

Dado que la conexión es completamente nueva en el servidor, se connectionId proporcionará un nuevo a la onreconnected devolución de llamada.Since the connection looks entirely new to the server, a new connectionId will be provided to the onreconnected callback.

Advertencia

El onreconnected parámetro de la devolución de llamada connectionId no se definirá si HubConnection se configuró para omitir la negociación.The onreconnected callback's connectionId parameter will be undefined if the HubConnection was configured to skip negotiation.

connection.onreconnected(connectionId => {
    console.assert(connection.state === signalR.HubConnectionState.Connected);

    document.getElementById("messageInput").disabled = false;

    const li = document.createElement("li");
    li.textContent = `Connection reestablished. Connected with connectionId "${connectionId}".`;
    document.getElementById("messagesList").appendChild(li);
});

withAutomaticReconnect() no configurará el HubConnection para reintentar errores de inicio inicial, por lo que los errores de inicio deben controlarse manualmente:withAutomaticReconnect() won't configure the HubConnection to retry initial start failures, so start failures need to be handled manually:

async function start() {
    try {
        await connection.start();
        console.assert(connection.state === signalR.HubConnectionState.Connected);
        console.log("SignalR Connected.");
    } catch (err) {
        console.assert(connection.state === signalR.HubConnectionState.Disconnected);
        console.log(err);
        setTimeout(() => start(), 5000);
    }
};

Si el cliente no se vuelve a conectar correctamente en los cuatro primeros intentos, HubConnection cambiará al Disconnected Estado y activará sus devoluciones de llamada OnClose .If the client doesn't successfully reconnect within its first four attempts, the HubConnection will transition to the Disconnected state and fire its onclose callbacks. Esto proporciona una oportunidad para informar a los usuarios de que la conexión se ha perdido permanentemente y recomienda actualizar la página:This provides an opportunity to inform users the connection has been permanently lost and recommend refreshing the page:

connection.onclose(error => {
    console.assert(connection.state === signalR.HubConnectionState.Disconnected);

    document.getElementById("messageInput").disabled = true;

    const li = document.createElement("li");
    li.textContent = `Connection closed due to error "${error}". Try refreshing this page to restart the connection.`;
    document.getElementById("messagesList").appendChild(li);
});

Con el fin de configurar un número personalizado de intentos de reconexión antes de desconectar o cambiar el tiempo de reconexión, withAutomaticReconnect acepta una matriz de números que representan el retraso en milisegundos que se debe esperar antes de iniciar cada intento de reconexión.In order to configure a custom number of reconnect attempts before disconnecting or change the reconnect timing, withAutomaticReconnect accepts an array of numbers representing the delay in milliseconds to wait before starting each reconnect attempt.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withAutomaticReconnect([0, 0, 10000])
    .build();

    // .withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior

En el ejemplo anterior HubConnection se configura para iniciar el intento de reconexión inmediatamente después de la pérdida de la conexión.The preceding example configures the HubConnection to start attempting reconnects immediately after the connection is lost. Esto también se aplica a la configuración predeterminada.This is also true for the default configuration.

Si se produce un error en el primer intento de reconexión, el segundo intento de reconexión también se iniciará inmediatamente en lugar de esperar 2 segundos como lo haría en la configuración predeterminada.If the first reconnect attempt fails, the second reconnect attempt will also start immediately instead of waiting 2 seconds like it would in the default configuration.

Si se produce un error en el segundo intento de reconexión, el tercer intento de reconexión se iniciará en 10 segundos, lo que volverá a ser como la configuración predeterminada.If the second reconnect attempt fails, the third reconnect attempt will start in 10 seconds which is again like the default configuration.

Después, el comportamiento personalizado difiere de nuevo del comportamiento predeterminado al detenerse después de que se produzca un error en el tercer intento de reconexión en lugar de intentar un intento de reconexión más en otros 30 segundos como lo haría en la configuración predeterminada.The custom behavior then diverges again from the default behavior by stopping after the third reconnect attempt failure instead of trying one more reconnect attempt in another 30 seconds like it would in the default configuration.

Si desea tener un mayor control sobre la temporización y el número de intentos de reconexión automática, withAutomaticReconnect acepta un objeto IRetryPolicy que implementa la interfaz, que tiene un único método denominado nextRetryDelayInMilliseconds .If you want even more control over the timing and number of automatic reconnect attempts, withAutomaticReconnect accepts an object implementing the IRetryPolicy interface, which has a single method named nextRetryDelayInMilliseconds.

nextRetryDelayInMilliseconds toma un único argumento con el tipo RetryContext .nextRetryDelayInMilliseconds takes a single argument with the type RetryContext. RetryContextTiene tres propiedades: previousRetryCount , elapsedMilliseconds y retryReason que son number , number y, Error respectivamente.The RetryContext has three properties: previousRetryCount, elapsedMilliseconds and retryReason which are a number, a number and an Error respectively. Antes del primer intento de reconexión, previousRetryCount y será elapsedMilliseconds cero, y será retryReason el error que provocó la pérdida de la conexión.Before the first reconnect attempt, both previousRetryCount and elapsedMilliseconds will be zero, and the retryReason will be the Error that caused the connection to be lost. Después de cada intento de reintento erróneo, se previousRetryCount incrementará en uno, se elapsedMilliseconds actualizará para reflejar la cantidad de tiempo empleado en la reconexión hasta el momento en milisegundos y el retryReason será el error que provocó el último intento de reconexión.After each failed retry attempt, previousRetryCount will be incremented by one, elapsedMilliseconds will be updated to reflect the amount of time spent reconnecting so far in milliseconds, and the retryReason will be the Error that caused the last reconnect attempt to fail.

nextRetryDelayInMilliseconds debe devolver un número que represente el número de milisegundos que se va a esperar antes del siguiente intento de reconexión o null si HubConnection debe dejar de volver a conectarse.nextRetryDelayInMilliseconds must return either a number representing the number of milliseconds to wait before the next reconnect attempt or null if the HubConnection should stop reconnecting.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withAutomaticReconnect({
        nextRetryDelayInMilliseconds: retryContext => {
            if (retryContext.elapsedMilliseconds < 60000) {
                // If we've been reconnecting for less than 60 seconds so far,
                // wait between 0 and 10 seconds before the next reconnect attempt.
                return Math.random() * 10000;
            } else {
                // If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
                return null;
            }
        }
    })
    .build();

Como alternativa, puede escribir código que volverá a conectar el cliente manualmente, tal como se muestra en reconexión manual.Alternatively, you can write code that will reconnect your client manually as demonstrated in Manually reconnect.

Volver a conectar manualmenteManually reconnect

En el código siguiente se muestra un enfoque típico de reconexión manual:The following code demonstrates a typical manual reconnection approach:

  1. Una función (en este caso, la start función) se crea para iniciar la conexión.A function (in this case, the start function) is created to start the connection.
  2. Llame a la start función en el controlador de eventos de la conexión onclose .Call the start function in the connection's onclose event handler.
async function start() {
    try {
        await connection.start();
        console.log("SignalR Connected.");
    } catch (err) {
        console.log(err);
        setTimeout(start, 5000);
    }
};

connection.onclose(start);

Una implementación del mundo real usaría una interrupción exponencial o reintentará un número especificado de veces antes de abandonarlo.A real-world implementation would use an exponential back-off or retry a specified number of times before giving up.

Recursos adicionalesAdditional resources

Por Rachel AppelBy Rachel Appel

La biblioteca de cliente de ASP.NET Core SignalR JavaScript permite a los desarrolladores llamar a código de concentrador de servidor.The ASP.NET Core SignalR JavaScript client library enables developers to call server-side hub code.

Vea o descargue el código de ejemplo (cómo descargarlo)View or download sample code (how to download)

Instalar el SignalR paquete de clienteInstall the SignalR client package

La SignalR biblioteca de cliente de JavaScript se entrega como un paquete NPM .The SignalR JavaScript client library is delivered as an npm package. En las secciones siguientes se describen diferentes formas de instalar la biblioteca de cliente de.The following sections outline different ways to install the client library.

Instalación con NPMInstall with npm

Si usa Visual Studio, ejecute los siguientes comandos desde la consola del administrador de paquetes en la carpeta raíz.If using Visual Studio, run the following commands from Package Manager Console while in the root folder. Para Visual Studio Code, ejecute los siguientes comandos desde el terminal integrado .For Visual Studio Code, run the following commands from the Integrated Terminal .

npm init -y
npm install @aspnet/signalr

NPM instala el contenido del paquete en la carpeta \ @aspnet\signalr\dist\browser node_modules .npm installs the package contents in the node_modules\@aspnet\signalr\dist\browser folder. Cree una nueva carpeta denominada signalr en la carpeta wwwroot \ lib .Create a new folder named signalr under the wwwroot\lib folder. Copie el archivo de signalr.js en la carpeta wwwroot\lib\signalr .Copy the signalr.js file to the wwwroot\lib\signalr folder.

Haga referencia al SignalR cliente de JavaScript en el <script> elemento.Reference the SignalR JavaScript client in the <script> element. Por ejemplo:For example:

<script src="~/lib/signalr/signalr.js"></script>

Uso de una Content Delivery Network (CDN)Use a Content Delivery Network (CDN)

Para usar la biblioteca de cliente sin el requisito previo de NPM, haga referencia a una copia hospedada en CDN de la biblioteca de cliente.To use the client library without the npm prerequisite, reference a CDN-hosted copy of the client library. Por ejemplo:For example:

<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.3/signalr.min.js"></script>

La biblioteca de cliente está disponible en las siguientes redes CDN:The client library is available on the following CDNs:

Instalación con LibManInstall with LibMan

LibMan se puede usar para instalar archivos de biblioteca de cliente específicos desde la biblioteca de cliente hospedada en CDN.LibMan can be used to install specific client library files from the CDN-hosted client library. Por ejemplo, agregue solo el archivo JavaScript reducida al proyecto.For example, only add the minified JavaScript file to the project. Para obtener más información sobre este enfoque, consulte Agregar la SignalR biblioteca de cliente.For details on that approach, see Add the SignalR client library.

Conexión a un concentradorConnect to a hub

El código siguiente crea e inicia una conexión.The following code creates and starts a connection. El nombre del centro no distingue mayúsculas de minúsculas.The hub's name is case insensitive.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .configureLogging(signalR.LogLevel.Information)
    .build();

async function start() {
    try {
        await connection.start();
        console.log("connected");
    } catch (err) {
        console.log(err);
        setTimeout(() => start(), 5000);
    }
};

connection.onclose(async () => {
    await start();
});

// Start the connection.
start();

/* this is here to show an alternative to start, with a then
connection.start().then(() => console.log("connected"));
*/

/* this is here to show another alternative to start, with a catch
connection.start().catch(err => console.error(err));
*/

Conexiones entre orígenesCross-origin connections

Normalmente, los exploradores cargan conexiones desde el mismo dominio que la página solicitada.Typically, browsers load connections from the same domain as the requested page. Sin embargo, hay ocasiones en las que se requiere una conexión a otro dominio.However, there are occasions when a connection to another domain is required.

Para evitar que un sitio malintencionado Lea datos confidenciales de otro sitio, las conexiones entre orígenes están deshabilitadas de forma predeterminada.To prevent a malicious site from reading sensitive data from another site, cross-origin connections are disabled by default. Para permitir una solicitud entre orígenes, habilítela en la Startup clase.To allow a cross-origin request, enable it in the Startup class.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SignalRChat.Hubs;

namespace SignalRChat
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddMvc();

            services.AddCors(options => options.AddPolicy("CorsPolicy", 
            builder => 
            {
                builder.AllowAnyMethod().AllowAnyHeader()
                       .WithOrigins("http://localhost:55830")
                       .AllowCredentials();
            }));

            services.AddSignalR();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseCors("CorsPolicy");
            app.UseSignalR(routes => 
            {
                routes.MapHub<ChatHub>("/chathub");
            });
            app.UseMvc();            
        }
    }
}

Llamar a métodos de Hub desde el clienteCall hub methods from client

Los clientes de JavaScript llaman a métodos públicos en los concentradores a través del método Invoke de HubConnection.JavaScript clients call public methods on hubs via the invoke method of the HubConnection. El invoke método acepta dos argumentos:The invoke method accepts two arguments:

  • Nombre del método de concentrador.The name of the hub method. En el ejemplo siguiente, el nombre del método en el concentrador es SendMessage .In the following example, the method name on the hub is SendMessage.

  • Cualquier argumento definido en el método de concentrador.Any arguments defined in the hub method. En el ejemplo siguiente, el nombre del argumento es message .In the following example, the argument name is message. El código de ejemplo utiliza la sintaxis de la función de flecha que se admite en las versiones actuales de todos los exploradores principales, excepto Internet Explorer.The example code uses arrow function syntax that is supported in current versions of all major browsers except Internet Explorer.

    connection.invoke("SendMessage", user, message).catch(err => console.error(err));
    

Nota

La llamada a métodos de concentrador desde un cliente solo se admite cuando se usa el SignalR servicio de Azure en el modo predeterminado .Calling hub methods from a client is only supported when using the Azure SignalR Service in Default mode. Para obtener más información, consulte preguntas más frecuentes (repositorio de github de Azure signalr).For more information, see Frequently Asked Questions (azure-signalr GitHub repository).

El invoke método devuelve un compromisode JavaScript.The invoke method returns a JavaScript Promise. PromiseSe resuelve con el valor devuelto (si existe) cuando el método en el servidor devuelve.The Promise is resolved with the return value (if any) when the method on the server returns. Si el método en el servidor produce un error, Promise se rechaza con el mensaje de error.If the method on the server throws an error, the Promise is rejected with the error message. Use los then catch métodos y en el Promise propio para controlar estos casos (o la await sintaxis).Use the then and catch methods on the Promise itself to handle these cases (or await syntax).

El send método devuelve un JavaScript Promise .The send method returns a JavaScript Promise. PromiseSe resuelve cuando el mensaje se ha enviado al servidor.The Promise is resolved when the message has been sent to the server. Si se produce un error al enviar el mensaje, Promise se rechaza con el mensaje de error.If there is an error sending the message, the Promise is rejected with the error message. Use los then catch métodos y en el Promise propio para controlar estos casos (o la await sintaxis).Use the then and catch methods on the Promise itself to handle these cases (or await syntax).

Nota

El uso de send no espera hasta que el servidor haya recibido el mensaje.Using send doesn't wait until the server has received the message. Por lo tanto, no es posible devolver datos ni errores del servidor.Consequently, it's not possible to return data or errors from the server.

Llamar a métodos de cliente desde el concentradorCall client methods from hub

Para recibir mensajes desde el concentrador, defina un método mediante el método on de la HubConnection .To receive messages from the hub, define a method using the on method of the HubConnection.

  • Nombre del método de cliente JavaScript.The name of the JavaScript client method. En el ejemplo siguiente, el nombre del método es ReceiveMessage .In the following example, the method name is ReceiveMessage.
  • Argumentos que el concentrador pasa al método.Arguments the hub passes to the method. En el ejemplo siguiente, el valor del argumento es message .In the following example, the argument value is message.
connection.on("ReceiveMessage", (user, message) => {
    const encodedMsg = `${user} says ${message}`;
    const li = document.createElement("li");
    li.textContent = encodedMsg;
    document.getElementById("messagesList").appendChild(li);
});

El código anterior en connection.on se ejecuta cuando el código del lado servidor lo llama mediante el SendAsync método.The preceding code in connection.on runs when server-side code calls it using the SendAsync method.

public async Task SendMessage(string user, string message)
{
    await Clients.All.SendAsync("ReceiveMessage", user, message);
}

SignalR determina el método de cliente al que se debe llamar haciendo coincidir el nombre del método y los argumentos definidos en SendAsync y connection.on .SignalR determines which client method to call by matching the method name and arguments defined in SendAsync and connection.on.

Nota

Como procedimiento recomendado, llame al método Start en el HubConnection después de on .As a best practice, call the start method on the HubConnection after on. Esto garantiza que los controladores se registren antes de que se reciban los mensajes.Doing so ensures your handlers are registered before any messages are received.

Registro y control de erroresError handling and logging

Encadenar un catch método al final del start método para controlar los errores del lado cliente.Chain a catch method to the end of the start method to handle client-side errors. Use console.error para generar errores en la consola del explorador.Use console.error to output errors to the browser's console.

connection.start().catch(err => console.error(err));

Configure el seguimiento del registro del lado cliente pasando un registrador y un tipo de evento al registro cuando se establezca la conexión.Set up client-side log tracing by passing a logger and type of event to log when the connection is made. Los mensajes se registran con el nivel de registro especificado y superior.Messages are logged with the specified log level and higher. Los niveles de registro disponibles son los siguientes:Available log levels are as follows:

  • signalR.LogLevel.Error: Mensajes de error.signalR.LogLevel.Error: Error messages. ErrorSolo registra mensajes.Logs Error messages only.
  • signalR.LogLevel.Warning: Mensajes de advertencia sobre posibles errores.signalR.LogLevel.Warning: Warning messages about potential errors. Registros Warning y Error mensajes.Logs Warning, and Error messages.
  • signalR.LogLevel.Information: Mensajes de estado sin errores.signalR.LogLevel.Information: Status messages without errors. Registra Information Warning mensajes, y Error .Logs Information, Warning, and Error messages.
  • signalR.LogLevel.Trace: Mensajes de seguimiento.signalR.LogLevel.Trace: Trace messages. Registra todo, incluidos los datos transportados entre el concentrador y el cliente.Logs everything, including data transported between hub and client.

Use el método configureLogging en HubConnectionBuilder para configurar el nivel de registro.Use the configureLogging method on HubConnectionBuilder to configure the log level. Los mensajes se registran en la consola del explorador.Messages are logged to the browser console.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .configureLogging(signalR.LogLevel.Information)
    .build();

Volver a conectar clientesReconnect clients

Volver a conectar manualmenteManually reconnect

Advertencia

Antes de 3,0, el cliente de JavaScript para SignalR no se vuelve a conectar automáticamente.Prior to 3.0, the JavaScript client for SignalR doesn't automatically reconnect. Debe escribir código que volverá a conectar el cliente manualmente.You must write code that will reconnect your client manually.

En el código siguiente se muestra un enfoque típico de reconexión manual:The following code demonstrates a typical manual reconnection approach:

  1. Una función (en este caso, la start función) se crea para iniciar la conexión.A function (in this case, the start function) is created to start the connection.
  2. Llame a la start función en el controlador de eventos de la conexión onclose .Call the start function in the connection's onclose event handler.
async function start() {
    try {
        await connection.start();
        console.log("connected");
    } catch (err) {
        console.log(err);
        setTimeout(() => start(), 5000);
    }
};

connection.onclose(async () => {
    await start();
});

Una implementación del mundo real usaría una interrupción exponencial o reintentará un número especificado de veces antes de abandonarlo.A real-world implementation would use an exponential back-off or retry a specified number of times before giving up.

Recursos adicionalesAdditional resources