【问题标题】:SignalR Serverless Report ProgressSignalR 无服务器报告进度
【发布时间】:2021-09-26 08:43:49
【问题描述】:

我正在尝试构建一个测试应用程序,以便我的 HTML 页面可以通过 SignalR 向 Azure 函数上的长时间运行方法发送消息,并且长时间运行的函数可以使用 SignalR 将进度报告回 HTML 页面。

有人知道怎么做吗?我在无服务器模式下将 .NET Core 3.1 用于该功能和 Azure SignalR 服务。我在网上四处查看,但似乎都是关于聊天,而我认为这是一个很常见的要求。

这就是我目前所拥有的......

using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace AzureSignalRFunctionTest
{
    public static class Function1
    {
        // Input Binding
        [FunctionName("negotiate")]
        public static SignalRConnectionInfo Negotiate(
            [HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req,
            [SignalRConnectionInfo(HubName = "TestHub")] SignalRConnectionInfo connectionInfo)
        {
            return connectionInfo;
        }

        // Trigger Binding
        [FunctionName("longrunningtask")]
        public static void LongRunningTask([SignalRTrigger("longrunningtask", "messages", "SendMessage")] InvocationContext invocationContext, [SignalRParameter] string message, ILogger logger)
        {
            logger.LogInformation($"Receive {message} from {invocationContext.ConnectionId}.");

            // what to put here?
            //var clients = invocationContext.GetClientsAsync().Result;

            //ReportProgress(invocationContext.ConnectionId, "Progress", ...);
            
            // Simulate Long running task
            System.Threading.Thread.Sleep(30000);
             
            // ReportProgress etc
        
        }

        // Output Binding
        [FunctionName("reportprogress")]
        public static Task ReportProgress(string connectionId, string message,
            [SignalR(HubName = "TestHub")] IAsyncCollector<SignalRMessage> signalRMessages)
        {
            return signalRMessages.AddAsync(
                new SignalRMessage
                {
                    ConnectionId = connectionId,
                    Target = "reportProgress",
                    Arguments = new[] { message }
                });
        }

    }
}

【问题讨论】:

    标签: signalr azure-signalr


    【解决方案1】:

    答案是这样做:

    using Microsoft.AspNetCore.Http;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.Azure.WebJobs.Extensions.SignalRService;
    using Microsoft.Extensions.Logging;
    using Microsoft.AspNetCore.SignalR;
    using System.Threading.Tasks;
    
    namespace MyAzureFunction
    {
        public class TestHub : ServerlessHub
        {
            // Input Binding
            [FunctionName("negotiate")]
            public SignalRConnectionInfo Negotiate(
                [HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req,
                [SignalRConnectionInfo(HubName="testhub")]SignalRConnectionInfo connectionInfo, ILogger logger)
            {
                logger.LogInformation($"ConnectionInfo: {connectionInfo.Url} {connectionInfo.AccessToken} {req.Path} {req.Query}");
    
                return connectionInfo;
            }
    
            // Trigger Binding
            [FunctionName("longrunningtask")]
            public async Task LongRunningTask(
                [SignalRTrigger] InvocationContext invocationContext,
                string message, ILogger logger)
            {
                logger.LogInformation($"Receive {message} from {invocationContext.ConnectionId}.");
    
                await Clients.Client(invocationContext.ConnectionId).SendAsync("reportProgress", message + " has started.");
    
                System.Threading.Thread.Sleep(10000);
    
                await Clients.Client(invocationContext.ConnectionId).SendAsync("reportProgress", message + " has ended.");
            }
        }
    }
    

    Html 看起来像这样:

    <h2>SignalR</h2>
    
    <div id="messages"></div>
    
    <form>
        <button type="submit" id="submitbtn">Submit</button>
    </form>
    
    @section Scripts {
    
        <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.19/signalr.min.js"></script>
        <script>
            let messages = document.querySelector('#messages');
            const apiBaseUrl = 'https://myazurefunction.azurewebsites.net';
            const connection = new signalR.HubConnectionBuilder()
                .withUrl(apiBaseUrl + '/api')
                .configureLogging(signalR.LogLevel.Information)
                .build();
    
            connection.on('reportProgress', (message) => {
                document.getElementById("messages").innerHTML = message;
            });
    
            function onConnected(connection) {
                document.getElementById('submitbtn').addEventListener('click', function (event) {
                    connection.send('longrunningtask', 'this is my message');
                    event.preventDefault();
                });
            }
    
            connection.start()
                .then(function () {
                    onConnected(connection)
                })
                .catch(console.error);
        </script>
    
    }
    

    如果您离开调用页面,并在函数应用运行时返回,则不会显示最终结果。如果这是一个要求而不仅仅是一个简单的进度条,那么我认为答案是通过用户 ID 进行身份验证,然后向该用户 ID 发送消息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多