If you are a beginner in SignalR and working on a project that consists of client and server components, and you want to consume the SignalR hub inside a controller, then you've come to the right place.
In this post, we will discuss how you can call a SignalR Core Hub method from a controller in ASP.NET Core.
In my example, the client is a JavaScript file that defines the hub connection and receives or sends messages.
In my server, which is an ASP.NET Core Web API, I simply want to send or receive messages from clients and save those messages on the server.
So here is My SignalR hub :
[Authorize]
public class ChatHub : Hub
{
public override Task OnDisconnectedAsync(Exception exception)
{
Debug.WriteLine("Client disconnected: " + Context.ConnectionId);
return base.OnDisconnectedAsync(exception);
}
public override Task OnConnectedAsync()
{
Debug.WriteLine("Client connected: " + Context.ConnectionId);
return base.OnConnectedAsync();
}
//Create Group for each user to chat sepeartely
public void SetUserChatGroup(string userId)
{
var id = Context.ConnectionId;
Debug.WriteLine($"Client {id} added to group " + userId);
Groups.AddToGroupAsync(Context.ConnectionId, userId.ToLower());
}
//Send message to user Group
public async Task SendMessageToOtherUser(ReceiveMessageDTO receiveMessageDTO)
{
if (Clients != null)
{
await Clients.Group(receiveMessageDTO.ReceiverId.ToString().ToLower()).SendAsync("ReceiveMessage", receiveMessageDTO);
}
}
//Send message to user Group
public async Task SendNotification(string userId)
{
if (Clients != null)
{
await Clients.Group(userId.ToLower()).SendAsync("Notification", "New notification recived!");
}
}
}
[Route("api/[controller]/[action]")]
[ApiController]
[Authorize]
public class ChatController : BaseController
{
DatabaseContext _context;
ChatHub _chatHub;
public ChatController(DatabaseContext context, ChatHub chatHub)
{
_context = context;
_chatHub = chatHub;
_logger = logger;
_dbThreadLogic = dbThreadLogic;
}
//api/Chat/SendMessage
[HttpPost]
public async Task<ActionResult<ResponseDTO<ReceiveMessageDTO>?>> SendMessage(SendMessageDTO sendMessage)
{
ResponseDTO<ReceiveMessageDTO> response = new ResponseDTO<ReceiveMessageDTO>();
response.StausCode = ResponseCode.Success;
try
{
var user = _context.Users.FirstOrDefault(a => a.Id == userId);
UserChatHistory chatHistory = new UserChatHistory();
chatHistory.Message = sendMessage.Message;
chatHistory.SenderUserId = userId;
chatHistory.ReceiverUserId = sendMessage.ReceiverId;
chatHistory.CreatedAt = DateTime.UtcNow;
var userRecentlyReceived = await _context.UserRecentlyReceivedMessage.Where(a => (a.ReceiverUserId == sendMessage.ReceiverId
&& a.SenderUserId == userId) || (a.ReceiverUserId == userId
&& a.SenderUserId == sendMessage.ReceiverId)).FirstOrDefaultAsync();
if (userRecentlyReceived == null)
{
userRecentlyReceived = new UserRecentlyReceivedMessage();
userRecentlyReceived.SenderUserId = userId;
userRecentlyReceived.ReceiverUserId = sendMessage.ReceiverId;
userRecentlyReceived.Message = sendMessage.Message;
userRecentlyReceived.LastUpdated = DateTime.UtcNow;
await _context.UserRecentlyReceivedMessage.AddAsync(userRecentlyReceived);
}
else
{
userRecentlyReceived.Message = sendMessage.Message;
userRecentlyReceived.LastUpdated = DateTime.UtcNow;
}
await _context.UserChatHistory.AddAsync(chatHistory);
await _context.SaveChangesAsync();
var message = new ReceiveMessageDTO
{
ReceiverId = sendMessage.ReceiverId,
SenderName = user.FullName,
SenderId = userId,
Message = sendMessage.Message,
};
await _chatHub.SendMessageToOtherUser(message);
}
catch (Exception ex)
{
return StatusCode((int)HttpStatusCode.InternalServerError, ex.Message);
}
return Ok(response);
}
}
public class SendMessageDTO
{
public required Guid ReceiverId { get; set; }
public required string Message { get; set; }
}
public class ReceiveMessageDTO
{
public Guid SenderId { get; set; }
public string SenderName { get; set; }
public Guid ReceiverId { get; set; }
public string Message { get; set; }
}
[Route("api/[controller]")]
[ApiController]
public class ChatController : ControllerBase
{
private readonly IHubContext<ChatHub> _hubContext;
public ChatController(IHubContext<ChatHub> hubContext)
{
_hubContext = hubContext;
}
[HttpPost("send-message")]
public async Task<IActionResult> SendMessage(string senderName,string message)
{
// Invoke the SendMessage method on the SignalR hub
await _hubContext.Clients.All.SendAsync("ReceiveMessage",senderName, message);
return Ok();
}
}