ASP.NET Core SignalR cliente JavaScriptASP.NET Core SignalR JavaScript client

Por Rachel AppelBy Rachel Appel

A SignalR biblioteca de cliente ASP.NET Core JavaScript permite que os desenvolvedores chamem o código de Hub do lado do servidor.The ASP.NET Core SignalR JavaScript client library enables developers to call server-side hub code.

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

Instalar o SignalR pacote do clienteInstall the SignalR client package

A SignalR biblioteca de cliente JavaScript é entregue como um pacote NPM .The SignalR JavaScript client library is delivered as an npm package. As seções a seguir descrevem diferentes maneiras de instalar a biblioteca de cliente.The following sections outline different ways to install the client library.

Instalar com NPMInstall with npm

Para o Visual Studio, execute os seguintes comandos no console do Gerenciador de pacotes enquanto estiver na pasta raiz.For Visual Studio, run the following commands from Package Manager Console while in the root folder. Para Visual Studio Code, execute os seguintes comandos do terminal integrado.For Visual Studio Code, run the following commands from the Integrated Terminal.

npm init -y
npm install @microsoft/signalr

NPM instala o conteúdo do pacote na pasta \ @microsoft\signalr\dist\browser node_modules .npm installs the package contents in the node_modules\@microsoft\signalr\dist\browser folder. Crie uma nova pasta chamada signalr na pasta wwwroot \ lib .Create a new folder named signalr under the wwwroot\lib folder. Copie o arquivo de signalr.js para a pasta wwwroot\lib\signalr .Copy the signalr.js file to the wwwroot\lib\signalr folder.

Referencie o SignalR cliente JavaScript no <script> elemento.Reference the SignalR JavaScript client in the <script> element. Por exemplo:For example:

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

Usar uma CDN (rede de distribuição de conteúdo)Use a Content Delivery Network (CDN)

Para usar a biblioteca de cliente sem o pré-requisito NPM, faça referência a uma cópia hospedada em CDN da biblioteca de cliente.To use the client library without the npm prerequisite, reference a CDN-hosted copy of the client library. Por exemplo:For example:

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

A biblioteca de cliente está disponível no seguinte CDNs:The client library is available on the following CDNs:

Instalar com LibManInstall with LibMan

LibMan pode ser usado para instalar arquivos de biblioteca de cliente específicos da biblioteca de cliente hospedada na CDN.LibMan can be used to install specific client library files from the CDN-hosted client library. Por exemplo, adicione apenas o arquivo JavaScript reduzidos ao projeto.For example, only add the minified JavaScript file to the project. Para obter detalhes sobre essa abordagem, consulte Adicionar a SignalR biblioteca de cliente.For details on that approach, see Add the SignalR client library.

Conectar-se a um hubConnect to a hub

O código a seguir cria e inicia uma conexão.The following code creates and starts a connection. O nome do Hub não diferencia maiú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();

Conexões entre origensCross-origin connections

Normalmente, os navegadores carregam conexões do mesmo domínio que a página solicitada.Typically, browsers load connections from the same domain as the requested page. No entanto, há ocasiões em que uma conexão com outro domínio é necessária.However, there are occasions when a connection to another domain is required.

Importante

O código do cliente deve usar uma URL absoluta em vez de uma URL relativa.The client code must use an absolute URL instead of a relative URL. Alterar .withUrl("/chathub") para .withUrl("https://myappurl/chathub").Change .withUrl("/chathub") to .withUrl("https://myappurl/chathub").

Para impedir que um site mal-intencionado leia dados confidenciais de outro site, as conexões entre origens são desabilitadas por padrão.To prevent a malicious site from reading sensitive data from another site, cross-origin connections are disabled by default. Para permitir uma solicitação entre origens, habilite-a na Startup classe: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");
            });
        }
    }
}

Métodos do hub de chamadas do clienteCall hub methods from the client

Os clientes JavaScript chamam métodos públicos em hubs por meio do método Invoke de HubConnection.JavaScript clients call public methods on hubs via the invoke method of the HubConnection. O invoke método aceita:The invoke method accepts:

  • O nome do método de Hub.The name of the hub method.
  • Quaisquer argumentos definidos no método Hub.Any arguments defined in the hub method.

No exemplo a seguir, o nome do método no Hub é SendMessage .In the following example, the method name on the hub is SendMessage. O segundo e o terceiro argumentos passados para invoke mapear para os argumentos e os métodos do Hub 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);
}

Observação

Somente há suporte para métodos de Hub de chamada de um cliente ao usar o serviço do Azure SignalR no modo padrão .Calling hub methods from a client is only supported when using the Azure SignalR Service in Default mode. Para obter mais informações, consulte perguntas frequentes (repositório GitHub do Azure-signalr).For more information, see Frequently Asked Questions (azure-signalr GitHub repository).

O invoke método retorna uma promessade JavaScript.The invoke method returns a JavaScript Promise. O Promise é resolvido com o valor de retorno (se houver) quando o método no servidor retorna.The Promise is resolved with the return value (if any) when the method on the server returns. Se o método no servidor gerar um erro, o Promise será rejeitado com a mensagem de erro.If the method on the server throws an error, the Promise is rejected with the error message. Use async e await ou os Promise then métodos e catch para lidar com esses casos.Use async and await or the Promise's then and catch methods to handle these cases.

Os clientes JavaScript também podem chamar métodos públicos em hubs por meio do método Send do HubConnection .JavaScript clients can also call public methods on hubs via the the send method of the HubConnection. Ao contrário do invoke método, o send método não aguarda uma resposta do servidor.Unlike the invoke method, the send method doesn't wait for a response from the server. O send método retorna um JavaScript Promise .The send method returns a JavaScript Promise. O Promise é resolvido quando a mensagem é enviada ao servidor.The Promise is resolved when the message has been sent to the server. Se houver um erro ao enviar a mensagem, o Promise será rejeitado com a mensagem de erro.If there is an error sending the message, the Promise is rejected with the error message. Use async e await ou os Promise then métodos e catch para lidar com esses casos.Use async and await or the Promise's then and catch methods to handle these cases.

Observação

sendO uso de não aguarda até que o servidor tenha recebido a mensagem.Using send doesn't wait until the server has received the message. Consequentemente, não é possível retornar dados ou erros do servidor.Consequently, it's not possible to return data or errors from the server.

Chamar métodos de cliente do HubCall client methods from the hub

Para receber mensagens do Hub, defina um método usando o método on do HubConnection .To receive messages from the hub, define a method using the on method of the HubConnection.

  • O nome do método de cliente JavaScript.The name of the JavaScript client method.
  • Argumentos que o Hub passa para o método.Arguments the hub passes to the method.

No exemplo a seguir, o nome do método é ReceiveMessage .In the following example, the method name is ReceiveMessage. Os nomes dos argumentos são user e 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);
});

O código anterior em connection.on é executado quando o código do lado do servidor o chama usando o 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 qual método de cliente chamar correspondendo o nome do método e os argumentos definidos em SendAsync e connection.on .SignalR determines which client method to call by matching the method name and arguments defined in SendAsync and connection.on.

Observação

Como prática recomendada, chame o método Start no HubConnection After on .As a best practice, call the start method on the HubConnection after on. Isso garante que seus manipuladores sejam registrados antes que todas as mensagens sejam recebidas.Doing so ensures your handlers are registered before any messages are received.

Registro em log e tratamento de errosError handling and logging

Use try e catch com async e await ou o Promise catch método do para manipular erros do lado do cliente.Use try and catch with async and await or the Promise's catch method to handle client-side errors. Use console.error para gerar erros de saída para o console do navegador:Use console.error to output errors to the browser's console:

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

Configure o rastreamento de log no lado do cliente passando um agente e um tipo de evento para registrar quando a conexão é feita.Set up client-side log tracing by passing a logger and type of event to log when the connection is made. As mensagens são registradas com o nível de log especificado e superior.Messages are logged with the specified log level and higher. Os níveis de log disponíveis são os seguintes:Available log levels are as follows:

  • signalR.LogLevel.Error: Mensagens de erro.signalR.LogLevel.Error: Error messages. Registra Error somente mensagens.Logs Error messages only.
  • signalR.LogLevel.Warning: Mensagens de aviso sobre erros potenciais.signalR.LogLevel.Warning: Warning messages about potential errors. Logs Warning e Error mensagens.Logs Warning, and Error messages.
  • signalR.LogLevel.Information: Mensagens de status sem erros.signalR.LogLevel.Information: Status messages without errors. Logs Information , Warning e Error mensagens.Logs Information, Warning, and Error messages.
  • signalR.LogLevel.Trace: Rastrear mensagens.signalR.LogLevel.Trace: Trace messages. Registra tudo, incluindo dados transportados entre o Hub e o cliente.Logs everything, including data transported between hub and client.

Use o método configureLogging no HubConnectionBuilder para configurar o nível de log.Use the configureLogging method on HubConnectionBuilder to configure the log level. As mensagens são registradas no console do navegador:Messages are logged to the browser console:

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

Reconectar clientesReconnect clients

Reconectar automaticamenteAutomatically reconnect

O cliente JavaScript para SignalR pode ser configurado para reconectar-se automaticamente usando o withAutomaticReconnect método em HubConnectionBuilder.The JavaScript client for SignalR can be configured to automatically reconnect using the withAutomaticReconnect method on HubConnectionBuilder. Ele não se reconectará automaticamente por padrão.It won't automatically reconnect by default.

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

Sem parâmetros, withAutomaticReconnect() o configura o cliente para aguardar 0, 2, 10 e 30 segundos, respectivamente, antes de tentar cada tentativa de reconexão, parando após quatro tentativas com falha.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 qualquer tentativa de reconexão, o HubConnection fará a transição para o HubConnectionState.Reconnecting estado e acionará seus onreconnecting retornos de chamada em vez de fazer a transição para o Disconnected estado e disparar seus onclose retornos de chamada como um HubConnection sem reconexão 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. Isso fornece uma oportunidade para avisar os usuários de que a conexão foi perdida e para desabilitar os elementos da interface do usuário.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);
});

Se o cliente se reconectar com êxito dentro de suas primeiras quatro tentativas, o HubConnection fará a transição de volta para o Connected estado e acionará seus onreconnected retornos de chamada.If the client successfully reconnects within its first four attempts, the HubConnection will transition back to the Connected state and fire its onreconnected callbacks. Isso fornece uma oportunidade de informar aos usuários que a conexão foi restabelecida.This provides an opportunity to inform users the connection has been reestablished.

Como a conexão é totalmente nova no servidor, um novo connectionId será fornecido para o retorno de onreconnected chamada.Since the connection looks entirely new to the server, a new connectionId will be provided to the onreconnected callback.

Aviso

O onreconnected parâmetro do retorno de chamada connectionId será indefinido se o HubConnection tiver sido configurado para ignorar a negociação.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() não configurará o HubConnection para tentar falhas de início inicial, portanto, as falhas de início precisam ser manipuladas 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);
    }
};

Se o cliente não se reconectar com êxito dentro de suas primeiras quatro tentativas, o HubConnection fará a transição para o Disconnected estado e acionará seus retornos de chamada fechamento .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. Isso fornece uma oportunidade de informar aos usuários que a conexão foi permanentemente perdida e recomenda atualizar a 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);
});

Para configurar um número personalizado de tentativas de reconexão antes de desconectar ou alterar o tempo de reconexão, o withAutomaticReconnect aceita uma matriz de números que representa o atraso em milissegundos para aguardar antes de iniciar cada tentativa de reconexão.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

O exemplo anterior configura o HubConnection para iniciar a tentativa de reconectar imediatamente após a perda da conexão.The preceding example configures the HubConnection to start attempting reconnects immediately after the connection is lost. Isso também é verdadeiro para a configuração padrão.This is also true for the default configuration.

Se a primeira tentativa de reconexão falhar, a segunda tentativa de reconexão também será iniciada imediatamente, em vez de esperar 2 segundos, como seria na configuração padrão.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.

Se a segunda tentativa de reconexão falhar, a terceira tentativa de reconexão será iniciada em 10 segundos, o que é novamente como a configuração padrão.If the second reconnect attempt fails, the third reconnect attempt will start in 10 seconds which is again like the default configuration.

O comportamento personalizado, em seguida, deriva novamente do comportamento padrão ao parar após a terceira tentativa de reconexão, em vez de tentar mais uma tentativa de reconexão em outros 30 segundos, como seria na configuração padrão.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.

Se você quiser ainda mais controle sobre o tempo e o número de tentativas de reconexão automática, o withAutomaticReconnect aceitará um objeto que implementa a IRetryPolicy interface, que tem um único método chamado 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 usa um único argumento com o tipo RetryContext .nextRetryDelayInMilliseconds takes a single argument with the type RetryContext. O RetryContext tem três propriedades: previousRetryCount , elapsedMilliseconds e retryReason que são a number , a number e uma Error respectivamente.The RetryContext has three properties: previousRetryCount, elapsedMilliseconds and retryReason which are a number, a number and an Error respectively. Antes da primeira tentativa de reconexão, previousRetryCount e elapsedMilliseconds será zero, e o retryReason será o erro que causou a perda da conexão.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. Após cada tentativa de repetição com falha, o previousRetryCount será incrementado em um, elapsedMilliseconds será atualizado para refletir a quantidade de tempo gasto reconectando até agora em milissegundos, e o retryReason será o erro que causou a falha da última tentativa de reconexão.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 deve retornar um número que representa o número de milissegundos a aguardar antes da próxima tentativa de reconexão ou null se o HubConnection deve parar de reconectar.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, você pode escrever um código que reconectará o cliente manualmente, conforme demonstrado na reconexão manual.Alternatively, you can write code that will reconnect your client manually as demonstrated in Manually reconnect.

Reconectar manualmenteManually reconnect

O código a seguir demonstra uma abordagem de reconexão manual típica:The following code demonstrates a typical manual reconnection approach:

  1. Uma função (nesse caso, a start função) é criada para iniciar a conexão.A function (in this case, the start function) is created to start the connection.
  2. Chame a start função no manipulador de eventos da conexão 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);

Uma implementação do mundo real usaria um retirada exponencial ou tentaria um número especificado de vezes antes de desistir.A real-world implementation would use an exponential back-off or retry a specified number of times before giving up.

Recursos adicionaisAdditional resources

Por Rachel AppelBy Rachel Appel

A SignalR biblioteca de cliente ASP.NET Core JavaScript permite que os desenvolvedores chamem o código de Hub do lado do servidor.The ASP.NET Core SignalR JavaScript client library enables developers to call server-side hub code.

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

Instalar o SignalR pacote do clienteInstall the SignalR client package

A SignalR biblioteca de cliente JavaScript é entregue como um pacote NPM .The SignalR JavaScript client library is delivered as an npm package. As seções a seguir descrevem diferentes maneiras de instalar a biblioteca de cliente.The following sections outline different ways to install the client library.

Instalar com NPMInstall with npm

Se estiver usando o Visual Studio, execute os seguintes comandos no console do Gerenciador de pacotes enquanto estiver na pasta raiz.If using Visual Studio, run the following commands from Package Manager Console while in the root folder. Para Visual Studio Code, execute os seguintes comandos do terminal integrado.For Visual Studio Code, run the following commands from the Integrated Terminal.

npm init -y
npm install @aspnet/signalr

NPM instala o conteúdo do pacote na pasta \ @aspnet\signalr\dist\browser node_modules .npm installs the package contents in the node_modules\@aspnet\signalr\dist\browser folder. Crie uma nova pasta chamada signalr na pasta wwwroot \ lib .Create a new folder named signalr under the wwwroot\lib folder. Copie o arquivo de signalr.js para a pasta wwwroot\lib\signalr .Copy the signalr.js file to the wwwroot\lib\signalr folder.

Referencie o SignalR cliente JavaScript no <script> elemento.Reference the SignalR JavaScript client in the <script> element. Por exemplo:For example:

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

Usar uma CDN (rede de distribuição de conteúdo)Use a Content Delivery Network (CDN)

Para usar a biblioteca de cliente sem o pré-requisito NPM, faça referência a uma cópia hospedada em CDN da biblioteca de cliente.To use the client library without the npm prerequisite, reference a CDN-hosted copy of the client library. Por exemplo:For example:

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

A biblioteca de cliente está disponível no seguinte CDNs:The client library is available on the following CDNs:

Instalar com LibManInstall with LibMan

LibMan pode ser usado para instalar arquivos de biblioteca de cliente específicos da biblioteca de cliente hospedada na CDN.LibMan can be used to install specific client library files from the CDN-hosted client library. Por exemplo, adicione apenas o arquivo JavaScript reduzidos ao projeto.For example, only add the minified JavaScript file to the project. Para obter detalhes sobre essa abordagem, consulte Adicionar a SignalR biblioteca de cliente.For details on that approach, see Add the SignalR client library.

Conectar-se a um hubConnect to a hub

O código a seguir cria e inicia uma conexão.The following code creates and starts a connection. O nome do Hub não diferencia maiú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));
*/

Conexões entre origensCross-origin connections

Normalmente, os navegadores carregam conexões do mesmo domínio que a página solicitada.Typically, browsers load connections from the same domain as the requested page. No entanto, há ocasiões em que uma conexão com outro domínio é necessária.However, there are occasions when a connection to another domain is required.

Para impedir que um site mal-intencionado leia dados confidenciais de outro site, as conexões entre origens são desabilitadas por padrão.To prevent a malicious site from reading sensitive data from another site, cross-origin connections are disabled by default. Para permitir uma solicitação entre origens, habilite-a na Startup classe.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();            
        }
    }
}

Métodos do hub de chamadas do clienteCall hub methods from client

Os clientes JavaScript chamam métodos públicos em hubs por meio do método Invoke de HubConnection.JavaScript clients call public methods on hubs via the invoke method of the HubConnection. O invoke método aceita dois argumentos:The invoke method accepts two arguments:

  • O nome do método de Hub.The name of the hub method. No exemplo a seguir, o nome do método no Hub é SendMessage .In the following example, the method name on the hub is SendMessage.

  • Quaisquer argumentos definidos no método Hub.Any arguments defined in the hub method. No exemplo a seguir, o nome do argumento é message .In the following example, the argument name is message. O código de exemplo usa a sintaxe de função de seta que tem suporte nas versões atuais de todos os principais navegadores, exceto o 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));
    

Observação

Somente há suporte para métodos de Hub de chamada de um cliente ao usar o serviço do Azure SignalR no modo padrão .Calling hub methods from a client is only supported when using the Azure SignalR Service in Default mode. Para obter mais informações, consulte perguntas frequentes (repositório GitHub do Azure-signalr).For more information, see Frequently Asked Questions (azure-signalr GitHub repository).

O invoke método retorna uma promessade JavaScript.The invoke method returns a JavaScript Promise. O Promise é resolvido com o valor de retorno (se houver) quando o método no servidor retorna.The Promise is resolved with the return value (if any) when the method on the server returns. Se o método no servidor gerar um erro, o Promise será rejeitado com a mensagem de erro.If the method on the server throws an error, the Promise is rejected with the error message. Use os then catch métodos e na Promise própria para lidar com esses casos (ou await sintaxe).Use the then and catch methods on the Promise itself to handle these cases (or await syntax).

O send método retorna um JavaScript Promise .The send method returns a JavaScript Promise. O Promise é resolvido quando a mensagem é enviada ao servidor.The Promise is resolved when the message has been sent to the server. Se houver um erro ao enviar a mensagem, o Promise será rejeitado com a mensagem de erro.If there is an error sending the message, the Promise is rejected with the error message. Use os then catch métodos e na Promise própria para lidar com esses casos (ou await sintaxe).Use the then and catch methods on the Promise itself to handle these cases (or await syntax).

Observação

sendO uso de não aguarda até que o servidor tenha recebido a mensagem.Using send doesn't wait until the server has received the message. Consequentemente, não é possível retornar dados ou erros do servidor.Consequently, it's not possible to return data or errors from the server.

Chamar métodos de cliente do HubCall client methods from hub

Para receber mensagens do Hub, defina um método usando o método on do HubConnection .To receive messages from the hub, define a method using the on method of the HubConnection.

  • O nome do método de cliente JavaScript.The name of the JavaScript client method. No exemplo a seguir, o nome do método é ReceiveMessage .In the following example, the method name is ReceiveMessage.
  • Argumentos que o Hub passa para o método.Arguments the hub passes to the method. No exemplo a seguir, o valor do argumento é 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);
});

O código anterior em connection.on é executado quando o código do lado do servidor o chama usando o 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 qual método de cliente chamar correspondendo o nome do método e os argumentos definidos em SendAsync e connection.on .SignalR determines which client method to call by matching the method name and arguments defined in SendAsync and connection.on.

Observação

Como prática recomendada, chame o método Start no HubConnection After on .As a best practice, call the start method on the HubConnection after on. Isso garante que seus manipuladores sejam registrados antes que todas as mensagens sejam recebidas.Doing so ensures your handlers are registered before any messages are received.

Registro em log e tratamento de errosError handling and logging

Encadear um catch método ao final do start método para manipular erros do lado do cliente.Chain a catch method to the end of the start method to handle client-side errors. Use console.error para gerar erros de saída para o console do navegador.Use console.error to output errors to the browser's console.

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

Configure o rastreamento de log no lado do cliente passando um agente e um tipo de evento para registrar quando a conexão é feita.Set up client-side log tracing by passing a logger and type of event to log when the connection is made. As mensagens são registradas com o nível de log especificado e superior.Messages are logged with the specified log level and higher. Os níveis de log disponíveis são os seguintes:Available log levels are as follows:

  • signalR.LogLevel.Error: Mensagens de erro.signalR.LogLevel.Error: Error messages. Registra Error somente mensagens.Logs Error messages only.
  • signalR.LogLevel.Warning: Mensagens de aviso sobre erros potenciais.signalR.LogLevel.Warning: Warning messages about potential errors. Logs Warning e Error mensagens.Logs Warning, and Error messages.
  • signalR.LogLevel.Information: Mensagens de status sem erros.signalR.LogLevel.Information: Status messages without errors. Logs Information , Warning e Error mensagens.Logs Information, Warning, and Error messages.
  • signalR.LogLevel.Trace: Rastrear mensagens.signalR.LogLevel.Trace: Trace messages. Registra tudo, incluindo dados transportados entre o Hub e o cliente.Logs everything, including data transported between hub and client.

Use o método configureLogging no HubConnectionBuilder para configurar o nível de log.Use the configureLogging method on HubConnectionBuilder to configure the log level. As mensagens são registradas no console do navegador.Messages are logged to the browser console.

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

Reconectar clientesReconnect clients

Reconectar manualmenteManually reconnect

Aviso

Antes de 3,0, o cliente JavaScript para SignalR não se reconectar automaticamente.Prior to 3.0, the JavaScript client for SignalR doesn't automatically reconnect. Você deve escrever um código que reconectará o cliente manualmente.You must write code that will reconnect your client manually.

O código a seguir demonstra uma abordagem de reconexão manual típica:The following code demonstrates a typical manual reconnection approach:

  1. Uma função (nesse caso, a start função) é criada para iniciar a conexão.A function (in this case, the start function) is created to start the connection.
  2. Chame a start função no manipulador de eventos da conexão 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();
});

Uma implementação do mundo real usaria um retirada exponencial ou tentaria um número especificado de vezes antes de desistir.A real-world implementation would use an exponential back-off or retry a specified number of times before giving up.

Recursos adicionaisAdditional resources