How to: Filter and format persistent chat room messages

[This is preliminary documentation and is subject to change.]

This topic shows how to filter or reformat message that a user is posting to a persistent chat room with code that you add to a simple persistent chat window.

Some organizations require that a message that is to be posted to a room comply with content and formatting constraints. For example, a securities brokerage may want to make sure that any trade instructions communicated in a chat room message do not contain numeric errors that might cause a disadvantageous trade. To make this message filtering possible, the Lync platform exposes an event that is raised when a message posting operation has started but is pending review by a logical message filter. The filter catches the event, runs filter logic on the message, updates the message as necessary, and then posts the message or cancels it.

Before you start the procedures in this topic, your application must declare and initialize a Microsoft.Lync.Model.LyncClient instance, and the client must be signed in. For more information, see How to: Sign In to Lync.

You must also have an instance of Microsoft.Lync.Model.Room.Room where the user has permission to read and post messages. For information about getting a room, see How to: Get persistent chat rooms. Your application must declare a button and a text box for rich-text formatted (RTF) content. The RTF text box accepts the message string to post and the button starts to post the message.

Code example

The following example references the namespaces that are used in the following Windows Forms examples.

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.Lync.Model;
using Microsoft.Lync.Model.Room;
using System.Collections;

The following example declares the class fields that are referenced later in this topic.

        /// <summary>
        /// The LyncClient class instance that encapsulates the Lync client platform
        /// </summary>
        private LyncClient _client=null;

        /// <summary>
        /// The Room instance that a user joins from the list of rooms that are queried, searched for, or gotten from the followed rooms list
        /// </summary>
        private Room _room = null;

        /// <summary>
        /// The Uri of the local user who can post a message to a chat room
        /// </summary>
        private string _senderUri = "";


When you have obtained a Microsoft.Lync.Model.Room.Room instance selected by a user, register for a set of room events so that you can receive a notification of a local user’s pending message post or messages posted to the room by other users.

To register for Room events

  1. Un-register for events on the previously selected room that is referenced by the _room class field.

  2. Set the _room class field to the newly selected room.

  3. Register for chat room events.

  4. Turn on room message filtering for the selected room.

  5. Read room properties and update the UI with the room title, description, and unread message count.

The following example registers for room events and reads room properties.

        /// <summary>
        /// Registers for message, state, and participant related events on a room.
        /// </summary>
        private void FillRoomProperties(Room room)
            if (_room != null)
                //Un-Register for event raised when a new message is posted to the room or the user has read a message.
                _room.UnreadMessageCountChanged -= room_UnreadMessageCountChanged;

                //Un-Register for the event raised when users have posted messages to the room.
                _room.MessagesReceived -= room_MessagesReceived;

                //Register for the event raised when the local user is posting a message and before the message is posted.
                _room.IsSendingMessage -= room_IsSendingMessage;

            _room = room;

            //Clear the messages from a previous room choice out of the message list box

            //Register for event raised when a new message is posted to the room or the user has read a message.
            _room.UnreadMessageCountChanged += new EventHandler<UnreadMessageCountChangedEventArgs>(room_UnreadMessageCountChanged);

            //Register for the event raised when users have posted messages to the room.
            _room.MessagesReceived += new EventHandler<RoomMessagesEventArgs>(room_MessagesReceived);

            //Enable the outgoing message filter.

            //Register for the event raised when the local user is posting a message and before the message is posted.
            _room.IsSendingMessage += new EventHandler<RoomMessageEventArgs>(room_IsSendingMessage);

            if (_room.Properties != null)
                if (_room.Properties[RoomProperty.Description] != null)
                    RoomDescription_label.Text = _room.Properties[RoomProperty.Description].ToString();
            txtUnreadMessageCountChanged.Text = _room.UnreadRoomMessageCount.ToString();

The outgoing message filtering logic is triggered in the Room.IsSendingMessage event. Your filter logic can take one of three actions:

  • Post the pending message that has no changes to the message text.

  • Replace some or all of the text in the message string before posting the message. This replacement can range from applying the results of a spelling checker algorithm, applying company messaging policy, applying standard message formatting, or translating the string from one language to another by calling methods on the Bing Translation service.

    Important note Important

    The text changes should be made for the message text in both plain text and RTF formats. If the same text replacement is not made to both formats, the resulting message will show inconsistent text across the two formats.

  • Cancel the message posting operation. In this case, no message is posted to the chat room.

    Important note Important

    The Lync 2013 Preview API platform has a timeout mechanism that posts a pending room message after 4 seconds if the Room.SendFilteredMessage is not called by your application code. This means that if no filtering action is taken by your application within 4 seconds, the message is posted to the room.

To filter a message

  1. Get the Microsoft.Lync.Model.Room.RoomMessage instance that encapsulates the pending message post.

  2. Get the plain-text message string and the RTF-formatted message string from the RoomMessage.MessageDictionary property.

  3. Apply custom filtering logic to each string.

  4. Replace the original strings in the RoomMessage.MessageDictionary with the updated message strings.

  5. Call the Room.SendFilteredMessage method with the enumeration of Microsoft.Lync.Model.Room.RoomMessageFilteringAction that applies your selected action.

Code examples

The following example filters a pending message in the Room.IsSendingMessage event.

        private void room_IsSendingMessage(object sender, RoomMessageEventArgs e)

                _filteredMessage = e.Message;

                string filteredMessageContentsPlain = _filteredMessage.MessageDictionary[RoomMessageFormat.PlainText].ToString();
                string filteredMessageContentsRtf = _filteredMessage.MessageDictionary[RoomMessageFormat.Rtf].ToString();

                //Parse pending message text for valid stock trade numerical values.
                string message = CustomStockTradeFilterLogic(filteredMessageContentsPlain);

                //Parse pending message text for valid stock trade numerical values.
                string RtfMessage = CustomStockTradeFilterLogic(filteredMessageContentsRtf);

                //If both the plain text and Rtf versions of the message pass the custom stock trade filter unchanged then
                //post the original message
                if (message.ToLower() == filteredMessageContentsPlain.ToLower() && RtfMessage.ToLower() == filteredMessageContentsRtf.ToLower())
                    _room.SendFilteredMessage(_filteredMessage, RoomMessageFilteringAction.Passed);
                    //If either the plain text or Rtf message strings fail the stock trade filter then
                    //cancel the message post. Neither message string is posted.
                    if (message == "Trade Canceled" || RtfMessage == "Trade Canceled")

                        //This filtering action cancels an entire message and all message strings that are contained
                        //within the message dictionary.
                        _room.SendFilteredMessage(_filteredMessage, RoomMessageFilteringAction.Canceled);

                        //Update the message dictionary with the plain text and Rtf string updates.

                        //It is not required that you replace both strings. You may replace one or the other
                        _filteredMessage.MessageDictionary[RoomMessageFormat.PlainText] = message;
                        _filteredMessage.MessageDictionary[RoomMessageFormat.Rtf] = RtfMessage;
                        _room.SendFilteredMessage(_filteredMessage, RoomMessageFilteringAction.Replaced);

            catch (Exception ex)


The following example takes the pending message text as a parameter, parses the message for custom content rules, makes corrections in the string, warns a user if corrections are made, and passes the updated string back to the Room.IsSendingMessage event handler.

        /// <summary>
        /// Replaces trade quantities and/or securities prices when either value is outside of
        /// acceptable trading parameters
        /// </summary>
        /// <param name="OriginalMessage">string. Original message to be posted.</param>
        /// <returns>string. Updated message string</returns>
        private string CustomStockTradeFilterLogic(string OriginalMessage)
            string updatedMessage = OriginalMessage;

            //Custom message parsing and text replacement would run here
            //---------------- text replacement algorithm ----------------------

            if (updatedMessage != OriginalMessage)
                Console.WriteLine("Your trade: " + OriginalMessage + " has been modified. The new trade is: " + updatedMessage);
            return updatedMessage;

Community Additions

© 2014 Microsoft