首页 > 解决方案 > 从 .Net 后端更新 React 前端

问题描述

我最近正在接近 React,我想知道如何从我的 ASP.NET 后端向所有前端发送一些更新,但首先让我解释一下自己。

我正在将一些输入从一个前端发送到后端。仅供参考,这是我的做法:

前端

    async SendInput(data) {
            await fetch('Status/ChangeState', {
                method: 'post',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(data)
            });
        }

后端

    [ApiController]
    [Route("[controller]")]
    public class StatusController : Controller
    {
        [HttpPost("ChangeState")]
        public void ChangeState([FromBody] short i)
        {
            //Do stuff here
        }
    }

现在我需要的是在其中一个更改此“状态”时保持所有已连接用户变量的更新。

我的第一个想法是使用 向后端重复发送 POST 或 GET 请求setInterval(),但即使用户不多,我仍然更喜欢长轮询或服务器发送事件之类的方法。

一个好的推荐方法是什么?如果可能的话,包括一个例子。

标签: c#reactjsapifrontendbackend

解决方案


在我看来,用于长轮询的最简单的状态管理器可以使用 TaskCompletionSource 创建。控制器使用 await 等待状态更改,并将结果作为 ActionResult 发送。客户端收到数据后立即打开与该控制器的连接。

但是,我只会将此实现用于非常小的项目,并且更多地用作说明性示例。对于较大的项目,可以使用 SignalR。

/// <summary>
/// Class for your state properties.
/// </summary>
public class State
{
    public string MyStateField1 { get; set; } = string.Empty;
    public string MyStateField2 { get; set; } = string.Empty;
}

/// <summary>
/// StateManager
/// Register with
///     services.AddSingleton<StateManager<State>>();
/// in ConfigureServices().
/// </summary>
/// <typeparam name="T">Type of the managed state class.</typeparam>
public class StateManager<T> where T : new()
{
    private readonly T _state;
    private TaskCompletionSource<T> _taskCompletition = new TaskCompletionSource<T>();

    private readonly object _taskCompletitionLock = new object();

    public StateManager()
    {
        _state = new T();
    }

    public void ChangeState(Action<T> updateFunction)
    {
        lock (_taskCompletitionLock)
        {
            updateFunction(_state);
            _taskCompletition.SetResult(_state);
            _taskCompletition = new TaskCompletionSource<T>();
        }
    }

    public Task<T> GetChangedState() => _taskCompletition.Task;
}

在 Startup.ConfigureServices 中注册:

services.AddSingleton<StateManager<State>>();

用法(在您的控制器中):

public async Task<IActionResult> StateMonitor()
{
    var newState = await _stateManager.GetChangedState();
    return Ok(newState);
}

public async Task<IActionResult> SetNewState()
{
    _stateManager.ChangeState(state => state.MyStateField1 = "My changed State");
    return NoContentResult();
}

推荐阅读