You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何搭建最简Serverless SignalR API及客户端?遇端点调用无响应问题

问题分析

核心问题在于Serverless环境(Azure Functions)下的SignalR实现逻辑和传统ASP.NET Core SignalR完全不同:

  • 传统ASP.NET Core依赖Hub上下文的Clients对象推送消息,但Azure Functions的Serverless SignalR通过触发器绑定+输出绑定实现功能,无法直接复用ASP版本的代码。
  • 你的SendMessage既未标记为Azure Function,也未配置SignalR相关绑定,前端调用时无法找到对应端点。
解决方案一:HTTP触发+SignalR输出绑定(适合HTTP调用场景)

修正后端代码

// 正常触发的Negotiate函数保持不变
[FunctionName("negotiate")]
public static SignalRConnectionInfo Negotiate(
    [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req,
    [SignalRConnectionInfo(HubName = "TestHub")] SignalRConnectionInfo connectionInfo)
{
    return connectionInfo;
}

// 修正后的Serverless版本SendMessage函数
[FunctionName("SendMessage")]
public static async Task<IActionResult> SendMessage(
    [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req,
    [SignalR(HubName = "TestHub")] IAsyncCollector<SignalRMessage> signalRMessages)
{
    // 解析前端传入的message参数
    var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    var data = JsonSerializer.Deserialize<dynamic>(requestBody);
    string message = data?.message;

    if (string.IsNullOrEmpty(message))
    {
        return new BadRequestObjectResult("消息不能为空");
    }

    // 处理消息(反转字符串)
    char[] stringArray = message.ToCharArray();
    Array.Reverse(stringArray);
    string reversedStr = new string(stringArray);

    // 通过SignalR输出绑定推送消息给所有客户端
    await signalRMessages.AddAsync(new SignalRMessage
    {
        Target = "ReceiveMessage",
        Arguments = new[] { reversedStr }
    });

    return new OkObjectResult("消息发送成功");
}

修正前端代码

const connection = new signalR.HubConnectionBuilder()
  .withUrl("http://localhost:7230/api/TestHub") // 关键:添加Hub名称TestHub
  .configureLogging(signalR.LogLevel.Information)
  .withAutomaticReconnect()
  .build();
    
// 接收消息的代码保持不变
connection.on("ReceiveMessage", (reply) => {
  console.log("[SignalR.ReceiveMessage] " + reply);
  serverReply.value = reply;
});

// ... 其他连接逻辑保持不变

// 发送消息的函数改为调用HTTP接口
async function sendToServer(){
  try {
    console.log("[SignalR.SendMessage] " + userInput.value);
    await fetch("http://localhost:7230/api/SendMessage", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({ message: userInput.value })
    });
  } catch (err) {
    console.error(err);
  }
}
解决方案二:SignalRTrigger触发(保持前端invoke调用习惯)

如果想让前端继续使用connection.invoke方式调用,可改用SignalRTrigger绑定接收客户端请求:

修正后端代码

[FunctionName("SendMessage")]
public static async Task SendMessage(
    [SignalRTrigger("TestHub", "messages", "SendMessage")] InvocationContext invocationContext,
    string message,
    [SignalR(HubName = "TestHub")] IAsyncCollector<SignalRMessage> signalRMessages)
{
    // 处理消息
    char[] stringArray = message.ToCharArray();
    Array.Reverse(stringArray);
    string reversedStr = new string(stringArray);

    // 推送消息给所有客户端
    await signalRMessages.AddAsync(new SignalRMessage
    {
        Target = "ReceiveMessage",
        Arguments = new[] { reversedStr }
    });
}

前端调整

仅需修改连接地址,sendToServer函数保持原有invoke逻辑即可:

const connection = new signalR.HubConnectionBuilder()
  .withUrl("http://localhost:7230/api/TestHub") // 添加Hub名称TestHub
  // ... 其他配置保持不变
  .build();

// sendToServer函数无需修改
async function sendToServer(){
  try {
    console.log("[SignalR.SendMessage] " + userInput.value);
    await connection.invoke("SendMessage", userInput.value);
  } catch (err) {
    console.error(err);
  }
}
必要配置说明
  1. 安装依赖包:确保项目已安装Microsoft.Azure.WebJobs.Extensions.SignalRService NuGet包
  2. 本地调试配置:在local.settings.json中添加SignalR连接字符串(可使用Azure SignalR模拟器)
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "AzureSignalRConnectionString": "Endpoint=http://localhost:5001;AccessKey=abc123;"
  }
}

内容的提问来源于stack exchange,提问作者ScumSprocket

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 02:36:14