基于Microsoft Bot Framework实现应用列表展示及详情查询功能求助
基于Microsoft Bot Framework的应用列表与详情实现方案
针对你的需求,以下是基于Bot Framework SDK v4的具体实现步骤和代码示例,适配基础开发者的技术栈:
核心流程梳理
- 通过瀑布对话收集用户账号、出生日期信息
- 调用你的数据API获取应用列表
- 用自适应卡片渲染带可交互入口的应用列表(普通Markdown链接无法触发机器人逻辑,自适应卡片的提交按钮可携带参数触发后续操作)
- 捕获用户点击事件,根据携带的
applicationID调用API获取详情并返回
代码示例(C#)
1. 基础结构与对话注册
using Microsoft.Bot.Builder; using Microsoft.Bot.Builder.Dialogs; using Microsoft.Bot.Schema; using Newtonsoft.Json; using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; public class ApplicationBot : ActivityHandler { private readonly ConversationState _conversationState; private readonly HttpClient _httpClient; private readonly DialogSet _dialogSet; public ApplicationBot(ConversationState conversationState, HttpClient httpClient) { _conversationState = conversationState; _httpClient = httpClient; _dialogSet = new DialogSet(_conversationState.CreateProperty<DialogState>(nameof(DialogState))); _dialogSet.Add(new WaterfallDialog("InfoCollection", new WaterfallStep[] { AskAccountStepAsync, AskBirthDateStepAsync, FetchAppsStepAsync })); // 注册文本提示器 _dialogSet.Add(new TextPrompt("AccountPrompt")); _dialogSet.Add(new TextPrompt("BirthDatePrompt")); } protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken) { var conversationData = await _conversationState.CreateProperty<ConversationData>(nameof(ConversationData)) .GetAsync(turnContext, () => new ConversationData(), cancellationToken); // 处理应用详情请求 if (turnContext.Activity.Value != null) { var submitData = JsonConvert.DeserializeObject<AppSubmitData>(turnContext.Activity.Value.ToString()); if (!string.IsNullOrEmpty(submitData.ApplicationId)) { await FetchAppDetailsAsync(turnContext, submitData.ApplicationId, cancellationToken); return; } } // 未收集信息则启动对话 var dialogContext = await _dialogSet.CreateContextAsync(turnContext, cancellationToken); if (dialogContext.Status == DialogTurnStatus.Empty) { await dialogContext.BeginDialogAsync("InfoCollection", null, cancellationToken); } else { await dialogContext.ContinueDialogAsync(cancellationToken); } await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken); } }
2. 瀑布对话步骤实现
// 询问账号 private async Task<DialogTurnResult> AskAccountStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { return await stepContext.PromptAsync("AccountPrompt", new PromptOptions { Prompt = MessageFactory.Text("请提供您的账号") }, cancellationToken); } // 询问出生日期 private async Task<DialogTurnResult> AskBirthDateStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { stepContext.Values["Account"] = stepContext.Result.ToString(); return await stepContext.PromptAsync("BirthDatePrompt", new PromptOptions { Prompt = MessageFactory.Text("请提供您的出生日期(格式:YYYY-MM-DD)") }, cancellationToken); } // 获取并渲染应用列表 private async Task<DialogTurnResult> FetchAppsStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) { var account = stepContext.Values["Account"].ToString(); var birthDate = stepContext.Result.ToString(); // 调用你的数据API(替换为实际地址) var response = await _httpClient.GetAsync($"https://your-api-domain/apps?account={account}&birthDate={birthDate}"); response.EnsureSuccessStatusCode(); var apps = await response.Content.ReadFromJsonAsync<List<Application>>(); // 构建自适应卡片 var card = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0)) { Body = new List<AdaptiveElement> { new AdaptiveTextBlock { Text = "您的应用列表", Size = AdaptiveTextSize.Large, Weight = AdaptiveTextWeight.Bold } }, Actions = new List<AdaptiveAction>() }; foreach (var app in apps) { card.Body.Add(new AdaptiveTextBlock { Text = $"应用ID: {app.ApplicationId}", Size = AdaptiveTextSize.Medium }); card.Body.Add(new AdaptiveTextBlock { Text = $"状态: {app.Status}", Margin = AdaptiveMargin.Small }); // 添加详情按钮,携带applicationID参数 card.Actions.Add(new AdaptiveSubmitAction { Title = "查看详情", Data = new { ApplicationId = app.ApplicationId } }); card.Body.Add(new AdaptiveHorizontalRule()); } // 发送卡片 await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(new Attachment { ContentType = AdaptiveCard.ContentType, Content = card }), cancellationToken); // 标记信息已收集 var conversationData = await _conversationState.CreateProperty<ConversationData>(nameof(ConversationData)) .GetAsync(stepContext.Context, () => new ConversationData(), cancellationToken); conversationData.IsInfoCollected = true; return await stepContext.EndDialogAsync(cancellationToken); }
3. 应用详情获取逻辑
private async Task FetchAppDetailsAsync(ITurnContext<IMessageActivity> turnContext, string appId, CancellationToken cancellationToken) { // 调用详情API(替换为实际地址) var response = await _httpClient.GetAsync($"https://your-api-domain/apps/details?appId={appId}"); response.EnsureSuccessStatusCode(); var details = await response.Content.ReadFromJsonAsync<ApplicationDetails>(); // 构造详情消息 var detailMsg = $"应用详情:\n" + $"应用ID: {details.ApplicationId}\n" + $"申请日期: {details.ApplicationDate:yyyy-MM-dd}\n" + $"状态: {details.Status}\n" + $"备注: {details.Remarks ?? "无"}"; await turnContext.SendActivityAsync(detailMsg, cancellationToken: cancellationToken); } // 辅助实体类 public class ConversationData { public bool IsInfoCollected { get; set; } = false; } public class Application { public string Id { get; set; } // 适配API返回的拼写错误(applicaitonID) [JsonProperty("applicaitonID")] public string ApplicationId { get; set; } public string Status { get; set; } } public class ApplicationDetails { public string ApplicationId { get; set; } public System.DateTime ApplicationDate { get; set; } public string Status { get; set; } public string Remarks { get; set; } } public class AppSubmitData { public string ApplicationId { get; set; } }
关键注意事项
- 自适应卡片必要性:普通Markdown链接仅能跳转外部网页,无法触发机器人逻辑;
AdaptiveSubmitAction可携带参数直接触发后端处理,是实现需求的核心。 - API字段映射:你的API返回中
applicaitonID存在拼写错误(应为applicationID),需通过JsonProperty特性做字段映射,避免序列化失败。 - 错误处理:示例省略了API调用失败的分支,实际开发中需添加
try-catch块,返回友好提示(如“暂时无法获取数据,请稍后重试”)。 - 参数验证:收集用户信息时需添加格式校验(如出生日期合法性),减少无效API调用。
开发建议
- 使用
ConversationState管理对话状态,避免重复询问用户信息。 - 在不同渠道(Web Chat、Teams)测试卡片显示效果,确保兼容性。
- 添加日志记录API请求/响应,便于排查问题。
- 若需支持多轮对话,可扩展对话逻辑实现信息补全或修改。
内容的提问来源于stack exchange,提问作者TechTurtle
相关产品推荐
相关产品推荐

