2015-08-11 2 views
3

Цель: облегчить чат между двумя пользователями, сохранив новое сообщение в БД (отправлено в веб-интерфейс) и вытолкнуть его на один клиент для прослушивания (SignalR).Интеграция приложения REST Web API с SignalR?

Вот мои проблемы:

  • Я не могу найти какие-либо шаблоны проектирования, которые касаются этого кроме Command and Query Responsibility Segregation (CQRS) Pattern и Event Sourcing Pattern. Оба они, похоже, сосредоточены на сложных приложениях реального времени. В моем приложении много традиционных функций REST, но пока единственным часовым компонентом является чат, поэтому нет необходимости использовать один из этих шаблонов.
  • Существует ли более простой способ интеграции веб-сайта REST (веб-API) с компонентом реального времени (SignalR)?
  • То, что я сейчас делаю, похоже, что я смешиваю две совершенно разные вещи.

Я думал попробовать:

  • Муфта мой обработчик POST к моему нажимной обработчик с помощью events - хотя я не уверен, что помогает мне, потому что я не ожидал, что «отправить сообщение» часть моего приложения, чтобы развить часть из части «получать».
  • Перемещение всей моей логики ввода в задание, выполняемое брокером сообщений, что опять не представляется необходимым, но создаст лучшее разделение. Мое понимание в соответствии с этим answer заключается в том, что SignalR использует брокер сообщений в памяти, чтобы широковещательная передача не ожидала получения сообщений, поэтому внешний брокер сообщений не нужен, если мне действительно не нужно масштабировать.

Возможно, мое приложение слишком просто, чтобы получить лучший дизайн?

Вот что я до сих пор:

public class chatPush 
{ 
    public chatPush(){} 

    public push(string msg) 
    { 
     try{ 
      string jsonMsg = JsonConvert.SerializeObject(msg); 
      await Clients.User(userId).send(jsonMsg); 
     } 
     catch 
     { 
      string errorMsg = //error with msg 
      await Clients.User(userId).send(errorMsg); 
     } 
    } 
} 

async Task<IHttpActionResult> PostMessage(Message msg) 

    db.Messages.Add(msg); 

    try 
    { 
     await db.SaveChangesAsync(); 
    } 
    catch 
    { 
     //return error in JSON 
    } 

    //if update succeeded push it out 
    _chatPush.push(jsonMsg); 

    return //Success or Error code 

ответ

4

Я не думаю, что вам нужно использовать какие-либо сложные шаблоны проектирования в то время как ваши потребности это просто. SignalR прекрасно работает только в POST/etc. обработчиков API и MVC.

Более сложный дизайн поможет вам, если вам нужно масштабировать до нескольких интерфейсных серверов, поскольку каждый пользователь будет подключаться только к одному из ваших хостов SignalR, поэтому вам нужно беспокоиться о постоянных сопоставлениях с подключением к пользователю через объединительную плату или базу данных. Но SignalR имеет приличную документацию для этого, когда вам это нужно.

С точкой зрения основной конструкции у меня есть несколько предложений:

1) Если у вас есть MessageHub на стороне сервера, создать MessageHubHelper легко передавать данные нужного пользователя.

[Authorize] 
public class MessageHub : Hub 
{ 
} 

public static class MessageHubHelper 
{ 
    private static readonly IHubContext _hubContext = 
     GlobalHost.ConnectionManager.GetHubContext<MessageHub>(); 

    public static IHubContext Context 
    { 
     get { return _hubContext; } 
    } 

    public static void Send(User user, Message message) 
    { 
     _hubContext.Clients.User(GetUserId(user)).Send(message); 
    } 

    public static void DoSomethingElse(User user, Message message) 
    { 
     _hubContext.Clients.User(GetUserId(user)).DoSomethingElse(message); 
    } 

    private static string GetUserId(User user) 
    { 
     return user.IdentityUser.UserName; 
    } 
} 

2) Убедитесь, что вы только передавать данные, если база данных совершает успеха (например, после SaveChangesAsync в попытке {}, если улов не будет бросать/вернуться рано).

3) Вам не нужно вручную обращаться с JSON. Просто нажмите объекты вниз, а библиотеки C# SignalR будут обрабатывать кодировку и декодирование.

4) По моему опыту SignalR может быть немного шелушащимся с его повторными соединениями, особенно с IUserIdProvider (я видел случаи, когда клиент и сервер думают, что они снова подключены, но никакие нажатия не проходят). Поэтому я рекомендую что-то вроде https://github.com/DamianEdwards/NDCLondon2013/tree/master/UserPresence, чтобы дать вам более надежное (или, по крайней мере, более отлаживаемое) управление присутствием пользователей.

Смежные вопросы