从 SignalR Hub 调用 Web-Api

Calling Web-Api from a SignalR Hub

我正在创建一个带有集成 SignalR 集线器的 WebApi 服务器。为简单起见,我使用的是在 List.

上运行的控制器
  [Route("api/[controller]")]
  [ApiController]
  public class ValuesController : ControllerBase
  {

    public static List<string> Source { get; set; } = new List<string>();
    public static int counter = 0;

    private IHubContext<ValuesHub, IValuesClient> hubContext;

    public ValuesController(IHubContext<ValuesHub, IValuesClient> hub)
    {
      Source.Add("bla" + counter);
      counter++;
      Source.Add("bla" + counter);
      counter++;
      this.hubContext = hub;
    }

    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
      return Source;
    }

    // GET api/values/x
    [HttpGet("{id}")]
    public ActionResult<string> Get(int id)
    {
      return Source[id];
    }

    // POST api/values
    [HttpPost]
    public void Post([FromBody] string value)
    {
      Source.Add(value);
    }

    // PUT api/values/x
    [HttpPut("{id}")]
    public void Put(int id, [FromBody] string value)
    {
      Source[id] = value;
    }

    // DELETE api/values/x
    [HttpDelete("{id}")]
    public void Delete(int id)
    {
      var item = Source[id];
      Source.Remove(item);
      Console.WriteLine("Outgoing message!");
      hubContext.Clients.All.ReceiveMessage("Message incoming", "Blaaaaa");
    }
  }
}

我的 Hub 还没有做任何特别的事情:

  public interface IValuesClient
  {
    Task ReceiveMessage(string value, string message);
    Task ReceiveMessage(string message);
  }

  public class ValuesHub : Hub<IValuesClient>
  {

    // private static ValuesController ctrl = Glo

    public override async Task OnConnectedAsync()
    {
      await Groups.AddToGroupAsync(Context.ConnectionId, "Users");
      Console.WriteLine("Client connected - Client-Id: {0}", Context.ConnectionId);
      await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
      await Groups.RemoveFromGroupAsync(Context.ConnectionId, "Users");
      Console.WriteLine("Client disconnected - Client-Id: {0}", Context.ConnectionId);
      Console.WriteLine("Disconnection due to: {0}", exception);
      await base.OnDisconnectedAsync(exception);
    }

    public async Task MessageToAll(string user, string message)
    {
      Console.WriteLine("SendMessage - User: {0} - Message: {1}", user, message);
      await Clients.All.ReceiveMessage(user, message);
    }

    public async Task MessageToCaller(string message)
    {
      Console.WriteLine("SendMessageToCaller: {0}", message);
      await Clients.Caller.ReceiveMessage(message);
    }
  }
}

同样为了简单起见,我不会详细说明为什么要实现这一点,但我希望服务器等待一定时间,然后在检测到断开连接后删除相应的值。假设我只想删除 Source 列表中的第一个元素。

如何从我的 OnDisconnectedAsync 函数中访问相应的控制器函数?

我想到的一个想法是在我的 Hub 中创建一个 HttpClient 并通过调用 e. G。 DELETE: http://localhost:5000/api/values/0。不过,我不得不承认这听起来像是一种相当可怕的方法。

所以如果我理解你的问题是你想要从你的集线器访问控制器上的方法?

如果是这种情况 - 在我看来,您有一个基本的设计缺陷。我会创建一个服务来处理你的控制器正在做的所有事情,然后将这个服务直接注入到集线器中。然后,您可以直接在集线器上的覆盖上使用该服务并对您的列表进行操作。如果不清楚我可以提供一个例子。

   public class ValuesHub : Hub<IValuesClient>
    {
   IListService _listService; 
 public ValuesHub (IListService listService)
    {
        _listService = listService;
    }

public override async Task OnConnectedAsync()
{
  await Groups.AddToGroupAsync(Context.ConnectionId, "Users");
  Console.WriteLine("Client connected - Client-Id: {0}", Context.ConnectionId);
  await base.OnConnectedAsync();
}

public override async Task OnDisconnectedAsync(Exception exception)
{
  await Groups.RemoveFromGroupAsync(Context.ConnectionId, "Users");
  Console.WriteLine("Client disconnected - Client-Id: {0}", Context.ConnectionId);
  Console.WriteLine("Disconnection due to: {0}", exception);
   //Call your methods here.
  _listService.RemoveFirstElement();
  await base.OnDisconnectedAsync(exception);
}

public async Task MessageToAll(string user, string message)
{
  Console.WriteLine("SendMessage - User: {0} - Message: {1}", user, message);
  await Clients.All.ReceiveMessage(user, message);
}

public async Task MessageToCaller(string message)
{
  Console.WriteLine("SendMessageToCaller: {0}", message);
  await Clients.Caller.ReceiveMessage(message);
}
   }
 }

这就是您的中心 - 请参阅下面的服务示例

  public class ListService : IListService
   {
    public void RemoveFirstElement()
    {
        //Delete Your Element here
    }
}

public interface IListService
{
    void RemoveFirstElement();
}

然后是你的startup.cs

 services.AddSingleton<IListService,ListService>();