The following diagram shows the solution architecture. Dashed lines depict associations (for example, an InteractiveBotSession instance is associated with both a user and a workflow instance) and red lines depict logic flow.
By default in Office Communications Server, only 200 concurrent subscribers can view an entity’s presence status. In a large organization this can be an issue, because only 200 users can subscribe to the bot’s presence. The sample application uses Always Online (Automaton) to relax this limitation. Only enterprise users can contact the bot; federated and public cloud users do not have access. For more information, see the SetupPresenceContainer method in InteractiveBotCore.cs.
The bot framework is written with a SipEndpoint that registers against Office Communications Server as a regular client. This is the recommended way to code a bot with Office Communications Server to publish an Always Online presence. In InteractiveBotCore.cs, see the PublishPresenceState and PublishAutomaton methods.
To enable Office Communicator to display form data, the following registry setting is required.
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Communicator]
"EnableConversationWindowTabs"=dword:00000001
This setting is usually implemented by an administrator policy added by Office Communicator. This policy must be activated on the Office Communicator client to run the sample. The sample user should verify that this key is present in the registry on the Office Communicator client. You can add the registry key yourself, but before you modify the registry, make sure to back it up and that you understand how to restore the registry if a problem occurs.
The InteractiveBot sample application is divided into separate projects contained within a single Visual Studio 2005 solution. Several of these projects are described in the following sections. For more information, see the commented code in each project.
InteractiveBot Project
InteractiveBot is the main project in the sample and the only project that uses the Unified Communications Managed API. In particular, see the InteractiveBotCore.cs, InteractiveBotOfferAnswer.cs, and InteractiveBotSession.cs files. This project is responsible for all Unified Communications Managed API related operations including registering a SIP endpoint for the user account associated with the interactive bot (in the InteractiveBotTestDriver project’s App.config file) and managing SIP user sessions. It also manages the Windows Workflow Foundation runtime instance, which in turn, hosts a dedicated custom state machine workflow instance for each SIP user session.
The bot is designed to rely as much as possible on the custom workflow for its functionality. When a user session is established, the bot has three main responsibilities:
-
To process incoming messages from the user
-
To raise events to the bot's associated workflow instance
-
To provide methods that the workflow can invoke to send information back to the bot (its host), which subsequently passes this information to the user through Unified Communications Managed API operations
The bot engages in continual, state-driven “listen – raise – receive – send” operations during the life of each user session. The workflow handles state management and sends any configured data to the bot. The bot does not maintain state and has no awareness of which RSS feeds are configured prior to the user selecting a specific feed.
This design means that the bot and the workflow it hosts are loosely coupled, allowing for a more pluggable architecture. The bot only needs to support the communications contract between itself and the workflow. Note that the bot only supports the IBotWorkflowCommunications interface and does not implement it. That is, the bot merely raises events defined by the interface and provides delegates for the multi-threaded processing of methods exposed to the workflow by the CommunciationsServices class, which does implement the interface.
This loosely coupled architecture permits the workflow designer to configure services other than RSS feeds, all without any changes required on the bot. This assumes that the communications contract does not undergo changes that require bot changes. Workflows also provide a convenient way to configure services by setting custom activity dependency properties using the Visual Studio 2005 workflow design-time tools.
InteractiveBotCommunications Project
The InteractiveBotCommunications project contains two files that define the communications contract between the interactive bot and the workflow runtime. The IBotWorkflowCommunications interface defines seven events that the InteractiveBotSession instance can raise when valid user input is received from the Office Communicator client (menu items 1–5, B for back, and X for exit). It also defines events that notify the InteractiveBotSession instance when sessions are created and terminated.
Additionally, four methods are defined that the workflow can invoke to communicate back to the host bot. The UpdateBotUI method allows the workflow to send back a bot menu string that the InteractiveBotSession instance then sends through the Unified Communications Managed API to the end user’s Office Communicator client. The FetchRSSFeed method instructs the bot to grab the RSS feed data from the Internet Explorer 7 feed store when the user selects a feed. The SendSelectedFeedItem method instructs the bot to display a selected feed item in the Office Communicator client extensibility window. Finally, the TerminateSession method allows the workflow to terminate the SIP user session.
It is important to note that the BotWorkflowCommunicationEventArgs class and each method defined by the interface contain a GUID (globally unique identifier) for storing the workflow instance associated with the InteractiveBotSession instance. This is needed because the workflow runtime manages its own thread pool. Therefore, when the workflow calls back into the bot through one of its external methods, it has no way of knowing which InteractiveBotSession instance corresponds to the calling workflow instance. To keep the SIP user sessions synchronized, the CommunicationsService class exposes a generic Dictionary<Guid, InteractiveBotSession> property that allows lookup of the InteractiveBotSession instance through the workflow instance GUID.
InteractiveBotServiceRequestStateMachineWorkflow Project
The InteractiveBotServiceRequestStateMachineWorkflow project contains a single file that represents the custom state machine workflow that runs the interactive bot. The workflow consists mainly of custom ServiceState activities, HandleExternalEventActivity activities, and CallExternalMethodActivity activities. See the following sections for more information about the ServiceState activities, each of which represents an information service such as an RSS feed.
The workflow has four states. The design approach is basically to handle an external event raised by the host bot, process the event to set some local properties, transition to the next state, call an external method on the bot as part of the state’s initialization, and then wait for new external events (listen – process – transition – initialize/call).
The initial state is WaitingForInteractiveBotServiceRequest, which occurs when the workflow is instantiated and prior to receiving any user input that wakes up the bot. When any input is received from the end user to start an instant messaging session, the bot transitions to the WaitingForMainMenuSelection state. During this state’s initialization, the UpdateBotUI method is called to send the main menu to the bot and thus to the end user.
When the user selects one of the configured RSS feeds (menu items 1–5), the state transitions to one of the configured service states (for example, the MSNBCSportNewsRSSFeedSelected state). During the state initialization, the FetchRSSFeed method is called to send the RSS feed’s dependency property data (such as feed title, URL, maximum number of items displayed, and refresh interval) to the bot. When the bot receives this information, it passes it along to its BotFeedsManager instance, which returns formatted feed items retrieved from the Internet Explorer 7 RSS feed store. These feed items are then sent through the Unified Communications Managed API operations to the user’s Office Communicator client as a submenu for further selection.
The final state is the workflow’s terminated state, which the workflow transitions to when one of two workflow-level (in other words, global) HandleExternalEventActivity activities receive either the OnSessionTerminated or OnMenuItemX_Selected events, respectively.
InteractiveBotTestDriver Project
The InteractiveBotTestDriver project contains the console application that is used to start, pause, and shut down the InteractiveBotServer instance in the InteractiveBot project. Starting the server causes the SIP user associated with the interactive bot (as specified in the App.config file) to go from an offline to online status in the user’s Office Communicator client.
RSSFeedServer Project
The RSSFeedServer project contains code for creating and retrieving RSS feeds in the Internet Explorer 7 RSS feed store. It uses the COM-based Windows RSS Platform that comes with Internet Explorer 7 and Windows Vista. The BotFeedsManager class exposes methods for feed management, and the feed data itself is encapsulated in the custom BotFeed class.
ServiceStateActivity Project
The ServiceStateActivity project contains a single code file that defines a basic custom activity representing an RSS feed state. The sole purpose of this custom activity is to provide a workflow designer with a way to easily configure an RSS feed for use by the interactive bot. It achieves this by exposing seven dependency properties for feed metadata such as title and URL. These properties appear in the Visual Studio 2005 Properties pane when the custom activity (which appears in the Toolbox) is dragged to the workflow design surface. It is worth pointing out that a workflow designer can add more dependency properties, or even create an entirely different custom activity, to support a different service (for example, a Web service). As long as this service works properly with the communications contract defined in IBotWorkflowCommunications, no changes are needed on the host bot to support the modified or new service.