Вызов Web-Api из хаба SignalR - PullRequest
0 голосов
/ 21 ноября 2018

Я создаю сервер WebApi со встроенными концентраторами SignalR.Для простоты я использую контроллер, который работает на 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");
    }
  }
}

Мой концентратор пока не делает ничего особенного:

  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?

Одна идея, которую я пришёлнужно создать HttpClient внутри моего хаба и позволить хабу действовать здесь как клиент, позвонив, например, DELETE: http://localhost:5000/api/values/0.Я должен признать, что это звучит как довольно ужасный подход.

1 Ответ

0 голосов
/ 22 ноября 2018

Итак, если я понимаю, что ваша проблема в том, что у вас есть то, что вы хотите получить доступ к методам на контроллере из ваших концентраторов?

Если это так - мне кажется, что у вас есть фундаментальныйнедостаток дизайна.Я бы создал службу, которая обрабатывает все, что делает ваш контроллер, а затем внедрил бы эту службу прямо в концентратор.Затем вы можете использовать эту службу прямо в концентраторе переопределений и работать со своим списком.Если это неясно, я могу предоставить пример.

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