When we think of implementing chat functionality, Facebook, WhatsApp, and a few other names come to mind. In the chat feature, we would look for functionalities like sending and receiving messages, creating groups, displaying unread chat messages, broadcasting messages to all contacts, etc.
Recently, we have integrated a chat feature into the CRM system using Azure Communication (ACS) Chat SDK. With ACS SDK, we can incorporate a chat feature into our application without being an expert in the underlying technology of real-time messaging. Instead, it provides basic functionalities to have real-time communication.
As we developed the Chat functionality, we ran into the below feature restrictions related to the chat SDK. So I thought it would be helpful to share the list of limitations and how you can overcome those.
Service Limits:
Here are a few size limits while creating a chat thread and adding participants.
There are several other service limits of Chat SDK explained in-depth here.
Feature limits:
The functionalities that are missing from the Chat SDK are listed below. However, some are still being thought about and might be featured in future releases.
- Deleting the chat thread for one of the participants.
- Archive/Pin chat thread for a user.
GetThreads
API does not return the unread count and the last message received data for the thread.- Broadcast a message to every thread in which the user is a participant.
- Only text messaging is supported. Thus, to communicate multimedia, we must first store it in the cloud and then share the link.
Let's look at how we can put the aforementioned feature constraints into practice.
-
Archive/Pin/Delete chat thread
If we use the chat SDK inbuilt
DeleteThread
method it will delete the thread for every participant and can be done by the thread owner/creator. But in practice, participants might want to delete the thread just for themselves. We can achieve it by savingCommunicationUser
andThreads
data in DB and exposing some new APIs as mentioned below.- Add
CommunicationUser
,ChatThreads
, andChatThreadParticipants
tables in DB. We will save the thread statuses i.ePin
,Archive
, andDelete
inChatThreadParticipants
. - Create new APIs for creating
Communication Users
,Chat Threads
, andAdd Participants
. These APIs will internally call ACS Chat SDK methods and store details in DB. - Create API to update statuses such as
Archive/Pin/Delete
onChatThreadParticipants
table. - Instead of getting Threads directly from Chat SDK's
GetThreads
method, you need to expose a new APIGetUserThreads
to fetch threads data from the database. GetUserThreads
API will return all threads except ones that have been deleted by sorting them according to the status field inChatThreadParticipants
.
You can refer to this class diagram to better understand database schema.
This way we can implement an
Archive/Pin/Delete
feature for the Chat Thread. - Add
-
Manage unread count and the last message received:
Currently, the inbuilt
GetThreads
call returns the following response:{ "value": [ { "id": "19:uni01_zbnh3nt2dfuffezc3sox7dog7wfhk6y5qe2@thread.v2", "topic": "Chat with Samantha", "lastMessageReceivedOn": "2020-06-06T05:55:41.6460000Z" }, { "id": "19:a0dfe5fc10e04a7f8d8a64d455f4196d@thread.v2", "topic": "Presentation Brainstorming", "lastMessageReceivedOn": "2020-06-06T05:55:41.6460000Z" }, ] }
In order to save
UnreadCount
,LastMsg
, andLastMsgOn
data inChatThreadParticipants
will need to handleChatMessageReceivedInThread
events emitted by the ACS chat service. To handle this event will need to do the following things:-
Create an event grid trigger Azure Function for handling events. It will update the thread's last message received details and unread count.
[FunctionName("ChatEventHandler")] public async Task Run([EventGridTrigger] EventGridEvent e) { if (e.EventType == "Microsoft.Communication.ChatMessageReceivedInThread") { var data = e.Data.ToObjectFromJson<ChatMessageReceivedInThreadEventData>(); using (var dataContext = DbFactory.Create()) { // Update Last message detail on thread var thread = dataContext.ReadWriteRepository<Communication_Chat_Threads>() .AsQueryable() .Where(x => x.ThreadId == model.ThreadId) .FirstOrDefault(); if (thread != null) { thread.LastMessage = model.Message; thread.LastMessageOn = model.SendDate; } // Update UnreadCount for Participant var threadParticpant = dataContext.ReadWriteRepository<Communication_Chat_Thread_Participants>() .AsQueryable() .Where(x => x.ThreadId == model.ThreadId && x.ParticipantId != model.SenderId) .FirstOrDefault(); if (threadParticpant != null) { threadParticpant.UnreadCount = threadParticpant.UnreadCount + 1; } dataContext.Save(); } } }
-
To subscribe to chat events, go to the Events section of Azure Communication Services on the Azure Portal. As an event handler, add the above
ChatEventHandler
function endpoint. -
Create a new API to update the Unread count. This API will be called every time the user enters the chat thread, and the unread count will be set to 0.
-
Expose a new API
GetChatThreads
to get the thread list from DB.[HttpGet] [Route("getChatThreads")] public HttpResponseMessage GetChatThreads([FromUri]ChatThreadFilterViewModel filter { filter.UserId = CurrentUserServices.UserId; var threads = CommunicationChatWorkerServices.GetUserThreads(filter); return Request.CreateResponse(HttpStatusCode.OK, threads); }
GetUserThreads
will fetch data from the database as per our requirement. -
-
Broadcast Messaging:
Implementing the broadcast functionality is relatively simple since thread details and communication user information are maintained in a database. To do this, we must provide an API endpoint to broadcast messages to the threads in which the user is a participant. This API will utilize the chat SDKs
SendMessage
method.
So this is one of the ways, we can implement the aforementioned feature limitations by keeping track of CommunicationUser
, ChatThread
, and ParticipantDetails
in the database.
I hope the article was helpful. You can find more articles on implementing Azure Chat SDK here.
Thank you for sticking out till the end. Happy coding!