SignalR API 设计时的注意事项SignalR API design considerations

    本文提供了用于构建基于 SignalR 的 Api 的指南。

    将参数添加到 SignalR 集线器方法 (在客户端或服务器) 是重大更改这意味着较旧的客户端/服务器会在尝试调用不带适当数量的参数的方法时出现错误。但是,将属性添加到自定义对象参数是一项重大更改。这可以用于设计兼容的 Api 时可复原的客户端或服务器上的更改。

    例如,考虑如下所示的服务器端 API:

    JavaScript 客户端调用此方法使用,如下所示:

    1. connection.invoke("GetTotalLength", "value1");
    1. public async Task<string> GetTotalLength(string param1, string param2)
    2. {
    3. return param1.Length + param2.Length;
    4. }

    当旧客户端尝试调用此方法时,它会收到如下错误:

    1. Microsoft.AspNetCore.SignalR.HubException: Failed to invoke 'GetTotalLength' due to an error on the server.

    在服务器上,将看到一条日志消息如下:

    旧客户端仅发送一个参数,但较新版本的服务器 API 所需的两个参数。使用自定义对象作为参数提供了更大的灵活性。让我们重新设计要使用自定义对象的原始 API:

    1. public class TotalLengthRequest
    2. {
    3. public string Param1 { get; set; }
    4. }
    5. public async Task GetTotalLength(TotalLengthRequest req)
    6. {
    7. return req.Param1.Length;

    现在,客户端使用对象调用方法:

    1. connection.invoke("GetTotalLength", { param1: "value1" });
    1. public class TotalLengthRequest
    2. public string Param1 { get; set; }
    3. public string Param2 { get; set; }
    4. }
    5. public async Task GetTotalLength(TotalLengthRequest req)
    6. {
    7. var length = req.Param1.Length;
    8. if (req.Param2 != null)
    9. {
    10. length += req.Param2.Length;
    11. }
    12. return length;
    13. }

    当旧客户端发送一个参数,额外Param2属性将保留null你可以检测到通过检查由较旧的客户端发送的消息Param2null并应用默认值。新的客户端可以发送两个参数。

    相同的方法适用于在客户端上定义的方法。可以从服务器端发送自定义对象:

    1. await Clients.All.SendAsync("ReceiveMessage", new
    2. {
    3. Message = message
    4. });
    5. }

    在客户端上,访问Message属性,而无需使用参数:

    1. connection.on("ReceiveMessage", (req) => {
    2. appendMessageToChatWindow(req.message);
    3. });

    如果你稍后决定要将消息的发件人添加到负载,请向对象添加属性:

    1. public async Task Broadcast(string message)
    2. {
    3. await Clients.All.SendAsync("ReceiveMessage", new
    4. {
    5. Sender = Context.User.Identity.Name,
    6. Message = message
    7. });

    在这种情况下,新的客户端也是不提供的旧服务器的容错值。由于旧的服务器不会提供Sender值时,客户端检查以查看是否存在之前对其进行访问。