Azure SignalR: как вернуть ConnectionInfo, если вы еще не знаете UserId в параметрах?

У меня есть служба SignalR, которая использует IHostedService для доступа к SignalR в Azure. Я пытаюсь реализовать функцию Negotiate, которая возвращает SignalRConnectionInfo. Проблема в том, что мне нужно передать UserId в ConnectionInfo, но я еще не знаю его при заполнении параметров. Я использую .NET 8 в изолированном режиме и следую этим документам Microsoft.

Функция

[Function("Negotiate")]
public static string Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "SomeHub", UserId = "????")] string connectionInfo)
{
    Guid userId = // Get userId from database
    await signalRService.AddUserToGroupAll(userId);
    return connectionInfo; // How to get this when i don't know UserId in the parameters yet??
}

СигналRService

public class SignalRService(IConfiguration configuration)
{
    private ServiceHubContext _messageHubContext;

    public async Task AddUserToGroupAll(Guid userId)
    {
        await _messageHubContext.Groups.AddToGroupAsync(userId.ToString(), /** groupname **/);
    }

    #region IHostService Functions
    async Task IHostedService.StartAsync(CancellationToken cancellationToken)
    {
        using ServiceManager serviceManager = new ServiceManagerBuilder()
            .WithOptions(o => o.ConnectionString = configuration[ConfigurationConstants.AzureSignalRConnectionString])
            .BuildServiceManager();
        _messageHubContext = await serviceManager.CreateHubContextAsync("SomeHub", cancellationToken);
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        await _messageHubContext.DisposeAsync();
    }
    #endregion
}

Мой вопрос: как мне вернуть SignalRConnectionInfo в этом случае?

Спасибо!

Как упоминалось в MSDOC UserId не является обязательным. Изображение

Pravallika KV 12.06.2024 14:26
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
0
1
107
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если вы хотите согласовать анонимный сеанс, вы можете получить его из SignalRService, поэтому вам не нужно передавать UserId в функцию Negotiate.

[Function("Negotiate")]
public static async Task<IActionResult> Negotiate(
    [HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    FunctionContext context)
{
    var signalRService = (SignalRService)context.InstanceServices.GetService(typeof(SignalRService));
    var connectionInfo = await signalRService.GetSignalRConnectionInfo();

    return new OkObjectResult(connectionInfo);
}

Но я не использую анонимность и не использую IActionResult

Kars 11.06.2024 14:42

@Карс Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)]. Это анонимно и находится в вашем коде. Если вы не хотите использовать IActionResult, просто return connectionInfo;.

Architect Jamie 11.06.2024 14:52

В моем SignalRService нет метода GetSignalRConnectionInfo.

Kars 11.06.2024 15:31

Используйте приведенный ниже код, чтобы вернуть ConnectionInfo в изолированных функциях Azure.

  • Я создал изолированную функцию Azure .NET 8.0.
  • UserId — необязательный параметр, как указано в MSDOC, и ConnectionInfo может быть возвращено даже без передачи UserId.
public class Function1
{
    private readonly ILogger _logger;

    public Function1(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger("negotiate");
    }

    [Function("negotiate")]
    public HttpResponseData Negotiate(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req,
        [SignalRConnectionInfoInput(HubName = "HubValue", UserId  = "")] MyConnectionInfo connectionInfo)
    {
        _logger.LogInformation($"SignalR Connection URL = '{connectionInfo.Url}'");

        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
        response.WriteString($"Connection URL = '{connectionInfo.Url}'");
        
        return response;
    }
}

public class MyConnectionInfo
{
    public string Url { get; set; }

    public string AccessToken { get; set; }
}

Ответ консоли:

Azure Functions Core Tools
Core Tools Version:       4.0.5801 Commit hash: N/A +5ac2f09758b98257e728dd1b5576ce5ea9ef68ff (64-bit)
Function Runtime Version: 4.34.1.22669

[2024-06-12T12:45:03.702Z] Found C:\Users\uname\Source\Repos\FunctionApp18\FunctionApp18.csproj. Using for user secrets file configuration.
[2024-06-12T12:45:14.003Z] Azure Functions .NET Worker (PID: 12024) initialized in debug mode. Waiting for debugger to attach...
[2024-06-12T12:45:14.144Z] Worker process started and initialized.

Functions:

        negotiate: [POST] http://localhost:7065/api/negotiate

For detailed output, run func with --verbose flag.
[2024-06-12T12:45:19.095Z] Host lock lease acquired by instance ID '000000000000000000000000F72731CC'.
[2024-06-12T12:45:20.088Z] Executing 'Functions.negotiate' (Reason='This function was programmatically called via the host APIs.', Id=c31883d3-4125-4cea-9c89-2c6456b76b26)
[2024-06-12T12:45:20.918Z] SignalR Connection URL = 'https://functionapp17.service.signalr.net/client/?hub=hubvalue'
[2024-06-12T12:45:21.022Z] Executed 'Functions.negotiate' (Succeeded, Id=c31883d3-4125-4cea-9c89-2c6456b76b26, Duration=968ms)

Выход:

Спасибо за ответ. это работает, но проблема в том, что мне НУЖНО установить UserId в ConnectionInfo. Но наше приложение настроено так, что я могу получить его только из базы данных, поэтому у меня не будет его в параметрах функции. Как мне таким образом получить UserId в ConnectionInfo?

Kars 14.06.2024 15:22

Не могли бы вы задать новый вопрос, указав полную информацию о вашем требовании?

Pravallika KV 14.06.2024 15:24
Ответ принят как подходящий

ServiceHubContext имеет метод NegotiateAsync, к которому вы можете перейти NegotiationOptions. Вы можете установить там UserId.

Например:

var negotiationResponse = await _serviceHubContext.NegotiateAsync(new NegotiationOptions { 
    UserId = userId.ToString() 
});
var connInfo = new SignalRConnectionInfo {
    AccessToken = negotiationResponse.AccessToken,
    Url = negotiationResponse.Url
};

И теперь у вас есть согласованная информация с UserId.

Другие вопросы по теме