System Documentation
Overview
The application is a web-based chat workflow system built with ASP.NET Core MVC, SignalR, and an internal Workflow engine. Its primary function is to guide users through a series of steps, questions, or data entries in a chat-like interface. The main components include:
- Chat.cshtml – This Razor view hosts the front-end UI, allowing the user to enter their name, select a workflow, and see chat messages and adaptive cards.
-
PromptSparkHub – A SignalR hub that handles real-time communication between clients and the server, delegating workflow progression logic to the
ConversationService. -
ConversationService – Manages the conversation state and workflow progression for each user, using a thread-safe dictionary store (
ConcurrentDictionaryService<Conversation>). - ChatService – Handles AI or generative responses through a chat-completion library, streaming partial responses back to clients for an interactive feel.
- ConcurrentDictionaryService – Provides a simple in-memory store for conversation data.
User Story
As a user, I want to land on a webpage where I can enter my name, select a workflow, and join a guided conversation in a chat format. The system should lead me through questions and provide options in adaptive cards, ensuring my state is saved between interactions or page refreshes. I should not have to start from scratch on a page refresh and the conversation flow should be intuitive.
Architectural Flow
- User Enters Name: The user is prompted to input a name, after which a dropdown to pick a workflow appears.
-
Selecting a Workflow: A list of available workflows is fetched from the server and displayed. Once the user chooses a workflow, SignalR initializes and
SetUserNameis invoked on the hub to store their session data. -
Conversation Initialization: The
ConversationService.Lookupmethod retrieves or creates a new conversation, associating the user with the selected workflow’s start node. -
Chat Interaction: Users submit responses (typed or by clicking options). The
PromptSparkHub.SendMessagemethod forwards them to theConversationService. Depending on whether the response matches a predefined workflow answer, the user either progresses in the workflow or triggers the AI agent (ChatService) for a dynamic response. - Adaptive Card Rendering: Adaptive Cards are sent back to the user through SignalR. The page renders these cards, enabling structured input and further responses.
-
Conversation Persistence: All conversation data is stored in memory using the thread-safe
ConcurrentDictionaryService<Conversation>. Users can refresh the page and resume where they left off.
Key Components
- Text input for the user’s name
- Workflow selection dropdown
- A chat window that appends messages and adaptive cards
- JavaScript code to manage SignalR connection and dynamic UI updates
Inherits from Hub and serves as the gateway for real-time communication:
-
SendMessage(string conversationId, string message)– Processes user messages, orchestrating workflow progression. -
SetUserName(string conversationId, string userName, string workflowName)– Initializes a user’s conversation with the specified workflow.
Manages each user’s Conversation state via ConcurrentDictionaryService<Conversation>. Key methods:
-
Lookup– Retrieves or creates aConversationobject for a given conversation ID. -
ProcessUserResponse– Determines how to handle incoming user responses, either advancing in the workflow or invoking AI for an unscripted answer. -
GetAdaptiveCardForNode– Constructs a JSON string representing an Adaptive Card for the current workflow node. -
ProgressWorkflow– Moves the conversation from the current workflow node to the next node based on user input.
Integrates an AI or chatbot library to provide dynamic responses:
-
GenerateBotResponse– Generates a single consolidated response from the AI. -
EngageChatAgent– Streams partial AI responses to the client in real time, providing a more conversational feel.
Methods include GetOrAdd, Lookup, Save, and others for retrieving and updating stored items without collisions in a multi-user environment.
Technologies Demonstrated
Chat.cshtml and Index.cshtml. It provides the foundational model-view-controller pattern
and routing for handling HTTP endpoints.
ConversationService,
ChatService, and PromptSparkHub. It leverages C#'s async/await to streamline
concurrency in a modern, scalable manner.
An ASP.NET Core library for real-time communication. The PromptSparkHub class uses
SignalR to enable instantaneous updates between the server and multiple clients, making chat sessions
seamless and interactive without full page reloads.
SignalR is a library from Microsoft that makes it easy to build real-time, interactive applications with ASP.NET Core. It allows you to push updates to clients instantly and handle client-server communication in a more responsive way, without resorting to polling or manual refreshes. For example, a messaging app or a live dashboard can quickly notify users when new data becomes available, rather than relying on periodic checks. SignalR abstracts away many of the complexities of WebSocket connections, letting you focus on crafting features instead of worrying about low-level networking details.
One of the biggest benefits of SignalR is its automatic fallback mechanism. If a browser or network environment doesn’t support WebSockets, SignalR gracefully switches to other protocols like Server-Sent Events or Long Polling. This ensures compatibility across different devices and network conditions, all while giving you a single, cohesive API to work with. Because it’s built on top of ASP.NET Core, SignalR can tap into the framework’s features for middleware, dependency injection, and authentication, so you can maintain consistent architecture across your app.
In addition, SignalR integrates seamlessly with client-side libraries such as the official JavaScript client, making it straightforward to subscribe to real-time events, broadcast messages, or manage complex group connections. You can even scale out your SignalR solution using services like Azure SignalR Service, or by configuring Redis or Azure Service Bus backplanes. This flexibility means that whether you’re building a small chat app or a globally distributed system, SignalR can adapt to your needs.
Azure SignalR Service
Azure SignalR Service is a fully managed service that offloads the complexity of hosting and scaling real-time applications. Instead of deploying and managing your own SignalR infrastructure, you can point your ASP.NET Core or .NET application to the Azure SignalR endpoint, and let the service handle connection management, scale-out, and performance optimizations. This is particularly helpful when your application experiences high traffic spikes or when you need to maintain persistent connections for large numbers of concurrent users without constantly modifying your hosting environment.
One of the biggest advantages of Azure SignalR Service is its ability to seamlessly integrate with other Azure services and features. It supports both serverless (Azure Functions) and web-app-based hosting models, so you can choose whatever approach suits your application’s architecture. When new events occur in your app—like data updates or user actions—Azure SignalR Service quickly routes messages to connected clients, all while giving you the tools for fine-grained control over which users, groups, or broadcast channels receive the updates.
From a developer’s standpoint, the setup process largely involves adding the necessary NuGet packages and configuration to your ASP.NET Core app. After referencing your connection string, you can continue coding against the familiar SignalR APIs, which means you don’t need to drastically change your existing code or patterns. Azure SignalR Service also features built-in options for secure endpoints, diagnostics, and scaling tiers to meet your capacity and performance needs, making it an ideal solution for everything from small-scale demos to enterprise-grade applications.
Adaptive Cards is an open-source framework developed by Microsoft that allows you to create visually appealing, platform-agnostic card snippets. These cards can contain text, images, input elements, and actions, making it easy to build interactive user experiences in conversational platforms or web applications. With a single JSON schema, Adaptive Cards can be rendered consistently across a variety of channels, such as Microsoft Teams, Outlook, or even custom websites, saving considerable development effort in supporting different platforms.
One of the key benefits of Adaptive Cards is the separation between content and design. Designers and developers can focus on defining the structure and data, while clients or hosts handle the rendering according to their own style guidelines or theme. This helps ensure a cohesive look and feel within each host application, while still delivering rich interactions that range from simple text prompts to comprehensive forms with validation.
Adaptive Cards also simplify user input capture by providing built-in support for text inputs, toggles, and drop-down lists. When users submit these cards, developers can process the input data directly, enabling scenarios like multi-step workflows, surveys, or feedback forms. The framework’s extensibility means you can add custom card elements and actions to meet more specific needs, all while taking advantage of the automatic layout and styling principles that Adaptive Cards offers.
ConcurrentDictionaryService<T> secures conversation data from race conditions
when multiple users are simultaneously active. In a large-scale or long-lived environment,
consider a distributed cache or database.
Deployment & Scalability
This application can be deployed to hosting providers such as Azure or AWS, or run on-prem. By default,
the ConcurrentDictionary approach suffices for small to medium workloads. For higher concurrency
and more robust session management, consider:
- Using a distributed cache (e.g., Redis) or database for storing conversations.
- Scaling out SignalR with a backplane like Redis or Azure SignalR Service.
- Ensuring serverless or containerized deployments if continuous scaling is needed.
Security & Session Management
- HTTPS: Always serve the site over HTTPS to protect user data in transit.
- Session Tokens: Currently, conversation IDs are stored in localStorage on the client. If security is critical, tie conversations to authenticated sessions on the server.
- Input Sanitization: Validate and sanitize user inputs to prevent injection or malicious content in the chat.
Potential Future Enhancements
- Authentication/Authorization – Limit access to specific workflows based on user roles.
- Database Persistence – Replace or augment in-memory storage with a relational or NoSQL database for durability.
- Workflow Editor – Add a front-end interface to manage workflow nodes and branching logic dynamically.
- Analytics – Gather insights such as average completion time per workflow step, usage statistics, etc.
- AI Summarization – Summarize long chat history for better context or quick recall.