Associação de saída do Serviço do SignalR do Azure Functions

Use a associação de saída do SignalR para enviar uma ou mais mensagens usando o Serviço Azure SignalR. Você pode transmitir uma mensagem para:

  • Todos os clientes conectados
  • Clientes conectados em um grupo especificado
  • Clientes conectados autenticados como um usuário específico

A associação de saída também permite que você gerencie grupos, como adicionar um cliente ou usuário a um grupo, remover um cliente ou usuário de um grupo.

Para obter informações sobre a instalação e detalhes de configuração, confira a visão geral.

Exemplo

Difundir para todos os clientes

Você pode criar uma função C# usando um dos seguintes modos C#:

  • Modelo de trabalho isolado: função C# compilada executada em um processo de trabalho que está isolado do runtime. Um processo de trabalho isolado é necessário para dar suporte a funções C# em execução em LTS (suporte de longo prazo) e versões não LTS para .NET e .NET Framework.
  • Modelo em processo: função C# compilada que é executada no mesmo processo que o runtime do Azure Functions.
  • Script C#: usado principalmente ao criar funções C# no portal do Azure.

O exemplo a seguir mostra uma função que envia uma mensagem que usa a associação de saída a todos os clientes conectados. O newMessage é o nome do método a ser invocado em cada cliente.

[Function(nameof(BroadcastToAll))]
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
public static SignalRMessageAction BroadcastToAll([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
    using var bodyReader = new StreamReader(req.Body);
    return new SignalRMessageAction("newMessage")
    {
        // broadcast to all the connected clients without specifying any connection, user or group.
        Arguments = new[] { bodyReader.ReadToEnd() },
    };
}

Aqui estão os dados de associação no arquivo function.json:

function.json de exemplo:

{
  "type": "signalR",
  "name": "signalROutput",
  "hubName": "hubName1",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}
const { app, output } = require('@azure/functions');

const signalR = output.generic({
    type: 'signalR',
    name: 'signalR',
    hubName: 'hub',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

// You can use any other trigger type instead.
app.http('broadcast', {
    methods: ['GET'],
    authLevel: 'anonymous',
    extraOutputs: [signalR],
    handler: (request, context) => {
        context.extraOutputs.set(signalR, {
            "target": "newMessage",
            "arguments": [request.body]
        });
    }
});

Exemplos completos do PowerShell estão pendentes.

Aqui está o código Python:

def main(req: func.HttpRequest, signalROutput: func.Out[str]) -> func.HttpResponse:
    message = req.get_json()
    signalROutput.set(json.dumps({
        'target': 'newMessage',
        'arguments': [ message ]
    }))
@FunctionName("sendMessage")
@SignalROutput(name = "$return", HubName = "hubName1")
public SignalRMessage sendMessage(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Object> req) {

    SignalRMessage message = new SignalRMessage();
    message.target = "newMessage";
    message.arguments.add(req.getBody());
    return message;
}

Enviar para um usuário

Você só pode enviar uma mensagem para as conexões autenticadas como um usuário configurando a ID de usuário na mensagem do SignalR.

[Function(nameof(SendToUser))]
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
public static SignalRMessageAction SendToUser([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
    using var bodyReader = new StreamReader(req.Body);
    return new SignalRMessageAction("newMessage")
    {
        Arguments = new[] { bodyReader.ReadToEnd() },
        UserId = "userToSend",
    };
}

Aqui estão os dados de associação no arquivo function.json:

function.json de exemplo:

{
  "type": "signalR",
  "name": "signalROutput",
  "hubName": "hubName1",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}

Exemplos completos do PowerShell estão pendentes.

Aqui está o código Python:

def main(req: func.HttpRequest, signalROutput: func.Out[str]) -> func.HttpResponse:
    message = req.get_json()
    signalROutput.set(json.dumps({
        #message will only be sent to this user ID
        'userId': 'userId1',
        'target': 'newMessage',
        'arguments': [ message ]
    }))
@FunctionName("sendMessage")
@SignalROutput(name = "$return", HubName = "hubName1")
public SignalRMessage sendMessage(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Object> req) {

    SignalRMessage message = new SignalRMessage();
    message.userId = "userId1";
    message.target = "newMessage";
    message.arguments.add(req.getBody());
    return message;
}
const { app, output } = require('@azure/functions');

const signalR = output.generic({
    type: 'signalR',
    name: 'signalR',
    hubName: 'hub',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

app.http('sendToUser', {
    methods: ['GET'],
    authLevel: 'anonymous',
    extraOutputs: [signalR],
    handler: (request, context) => {
        context.extraOutputs.set(signalR, {
            "target": "newMessage",
            "arguments": [request.body],
            "userId": "userId1",
        });
    }
});

Enviar para um grupo

Você só pode enviar uma mensagem para as conexões que foram adicionadas a um grupo configurando o nome do grupo na mensagem do SignalR.

[Function(nameof(SendToGroup))]
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
public static SignalRMessageAction SendToGroup([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
    using var bodyReader = new StreamReader(req.Body);
    return new SignalRMessageAction("newMessage")
    {
        Arguments = new[] { bodyReader.ReadToEnd() },
        GroupName = "groupToSend"
    };
}

Aqui estão os dados de associação no arquivo function.json:

function.json de exemplo:

{
  "type": "signalR",
  "name": "signalROutput",
  "hubName": "hubName1",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}
const { app, output } = require('@azure/functions');

const signalR = output.generic({
    type: 'signalR',
    name: 'signalR',
    hubName: 'hub',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

app.http('sendToGroup', {
    methods: ['GET'],
    authLevel: 'anonymous',
    extraOutputs: [signalR],
    handler: (request, context) => {
        context.extraOutputs.set(signalR, {
            "target": "newMessage",
            "arguments": [request.body],
            "groupName": "myGroup",
        });
    }
});

Exemplos completos do PowerShell estão pendentes.

Aqui está o código Python:

def main(req: func.HttpRequest, signalROutput: func.Out[str]) -> func.HttpResponse:
    message = req.get_json()
    signalROutput.set(json.dumps({
        #message will only be sent to this group
        'groupName': 'myGroup',
        'target': 'newMessage',
        'arguments': [ message ]
    }))
@FunctionName("sendMessage")
@SignalROutput(name = "$return", HubName = "hubName1")
public SignalRMessage sendMessage(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Object> req) {

    SignalRMessage message = new SignalRMessage();
    message.groupName = "myGroup";
    message.target = "newMessage";
    message.arguments.add(req.getBody());
    return message;
}

Gerenciamento de grupos

O Serviço do SignalR permite a adição de usuários ou conexões aos grupos. Em seguida, é possível enviar mensagens a um grupo. Você pode usar a associação de saída de SignalR para gerenciar grupos.

Especifique SignalRGroupActionType para adicionar ou remover um membro. O exemplo a seguir remove um usuário de um grupo.

[Function(nameof(RemoveFromGroup))]
[SignalROutput(HubName = "chat", ConnectionStringSetting = "SignalRConnection")]
public static SignalRGroupAction RemoveFromGroup([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
    return new SignalRGroupAction(SignalRGroupActionType.Remove)
    {
        GroupName = "group1",
        UserId = "user1"
    };
}

Observação

Para fazer a associação correta de ClaimsPrincipal, você deve ter definido as configurações de autenticação no Azure Functions.

Aqui estão os dados de associação no arquivo function.json:

function.json de exemplo:

{
  "type": "signalR",
  "name": "signalROutput",
  "hubName": "hubName1",
  "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
  "direction": "out"
}
const { app, output } = require('@azure/functions');

const signalR = output.generic({
    type: 'signalR',
    name: 'signalR',
    hubName: 'hub',
    connectionStringSetting: 'AzureSignalRConnectionString',
});

// The following function adds a user to a group
app.http('addUserToGroup', {
    methods: ['POST'],
    authLevel: 'anonymous',
    extraOutputs: [signalR],
    handler: (request, context) => {
        context.extraOutputs.set(signalR, {
            "userId": req.query.userId,
            "groupName": "myGroup",
            "action": "add"
        });
    }
});

// The following function removes a user from a group
app.http('removeUserFromGroup', {
    methods: ['POST'],
    authLevel: 'anonymous',
    extraOutputs: [signalR],
    handler: (request, context) => {
        context.extraOutputs.set(signalR, {
            "userId": req.query.userId,
            "groupName": "myGroup",
            "action": "remove"
        });
    }
});

Exemplos completos do PowerShell estão pendentes.

O exemplo a seguir adiciona um usuário a um grupo.

def main(req: func.HttpRequest, signalROutput: func.Out[str]) -> func.HttpResponse:
    signalROutput.set(json.dumps({
        'userId': 'userId1',
        'groupName': 'myGroup',
        'action': 'add'
    }))

O exemplo a seguir remove um usuário de um grupo.

def main(req: func.HttpRequest, signalROutput: func.Out[str]) -> func.HttpResponse:
    signalROutput.set(json.dumps({
        'userId': 'userId1',
        'groupName': 'myGroup',
        'action': 'remove'
    }))

O exemplo a seguir adiciona um usuário a um grupo.

@FunctionName("addToGroup")
@SignalROutput(name = "$return", HubName = "hubName1")
public SignalRGroupAction addToGroup(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Object> req,
        @BindingName("userId") String userId) {

    SignalRGroupAction groupAction = new SignalRGroupAction();
    groupAction.action = "add";
    groupAction.userId = userId;
    groupAction.groupName = "myGroup";
    return action;
}

O exemplo a seguir remove um usuário de um grupo.

@FunctionName("removeFromGroup")
@SignalROutput(name = "$return", HubName = "hubName1")
public SignalRGroupAction removeFromGroup(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Object> req,
        @BindingName("userId") String userId) {

    SignalRGroupAction groupAction = new SignalRGroupAction();
    groupAction.action = "remove";
    groupAction.userId = userId;
    groupAction.groupName = "myGroup";
    return action;
}

Atributos

As bibliotecas C# em processo e de processo de trabalho isolado usam atributos para definir a função. Em vez disso, o script C# usa um arquivo de configuração function.json.

A tabela a seguir explica as propriedades do atributo SignalROutput.

Propriedade de atributo Descrição
HubName Esse valor deve ser definido como o nome do hub SignalR para o qual as informações de conexão são geradas.
ConnectionStringSetting O nome da configuração do aplicativo ou da coleção de configurações que contém a cadeia de conexão do Serviço do SignalR, cujo padrão é AzureSignalRConnectionString.

Anotações

A tabela a seguir explica as configurações com suporte para a anotação SignalROutput.

Configuração Descrição
nome Nome da variável usada no código de função para o objeto de informações de conexão.
hubName Esse valor deve ser definido como o nome do hub SignalR para o qual as informações de conexão são geradas.
connectionStringSetting O nome da configuração do aplicativo ou da coleção de configurações que contém a cadeia de conexão do Serviço do SignalR, cujo padrão é AzureSignalRConnectionString.

Configuração

A tabela a seguir explica as propriedades de configuração de associação que você define no arquivo function.json.

Propriedade function.json Descrição
tipo Deve ser definido como signalR.
direção Deve ser definido como out.
nome Nome da variável usada no código de função para o objeto de informações de conexão.
hubName Esse valor deve ser definido como o nome do hub SignalR para o qual as informações de conexão são geradas.
connectionStringSetting O nome da configuração do aplicativo ou da coleção de configurações que contém a cadeia de conexão do Serviço do SignalR, cujo padrão é AzureSignalRConnectionString.

Quando você estiver desenvolvendo localmente, adicione as configurações do aplicativo no arquivo local.settings.json na coleção Values.

Uso

Conexões

A connectionStringSetting propriedade é definida como uma chave nas configurações da aplicação que retorna um valor usado pelo runtime Functions para se conectar à instância do Serviço do Azure SignalR usada pela extensão. O valor dessa configuração de propriedade de conexão depende do tipo de conexão:

  • Conexão de identidade gerenciada: A connectionStringSetting propriedade é compartilhada <CONNECTION_NAME_PREFIX> por um grupo de configurações que, juntas, definem uma conexão baseada em identidade com o endpoint do serviço. Para mais informações, veja Definir conexões de identidade.
  • Referência Key Vault: A connectionStringSetting configuração de propriedade retorna uma referência ao Azure Key Vault para o local onde a cadeia de conexão é mantida centralmente. Para mais informações, veja Definir conexões do Key Vault.
  • Referência de App Configuration: A connectionStringSetting configuração de propriedade retorna uma referência ao Configuração de Aplicativos do Azure que retorna uma cadeia de conexão ou uma referência ao Key Vault. Para mais informações, veja Configuração de Aplicativos do Azure no artigo de conexões.
  • Connection string: A connectionStringSetting configuração de propriedade retorna a cadeia de conexão real do serviço SignalR. Como a cadeia de conexão contém chaves secretas compartilhadas, você deve considerar usar uma conexão de identidade gerenciada, sempre que possível. Para mais informações, veja Definir conexões.

Para saber mais sobre conexões de bindings, veja Gerenciar conexão no Azure Functions. Para obter uma cadeia de conexão, siga os passos mostrados em Como obter conexões strings.

O host de Funções procura uma chave ou prefixo de chave nomeado AzureSignalRConnectionString ao se conectar ao seu serviço SignalR. Caso contrário, ele usa o valor-chave definido em connectionStringSetting para obter as informações de conexão necessárias.

Próximas etapas