【问题标题】:Calling Web-Api from a SignalR Hub从 SignalR Hub 调用 Web-Api
【发布时间】:2018-11-21 15:26:55
【问题描述】:

我正在创建一个带有集成 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 让 Hub 在此处充当客户端。 G。 DELETE: http://localhost:5000/api/values/0。不过,我不得不承认这听起来是一种相当可怕的方法。

【问题讨论】:

  • 取决于您需要等待多长时间,以及您如何处理等待异步,恕我直言,您可能会阻止线程不好,最好在准备好时调用它,为什么使用 HTTP 客户端可怕?

标签: .net-core asp.net-core-webapi signalr-hub asp.net-core-signalr


【解决方案1】:

如果我理解您的问题是您想从集线器访问控制器上的方法吗?

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

   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>();

【讨论】:

猜你喜欢
  • 2019-01-28
  • 1970-01-01
  • 1970-01-01
  • 2018-04-04
  • 1970-01-01
  • 1970-01-01
  • 2019-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多