You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Microsoft Bot Framework中读取用户字符串列表及客户技能收集表单咨询

Hey there! Let's tackle your chatbot project questions—first fixing that form model code, then covering how to collect a list of skills from users in Microsoft Bot Framework.

1. Fixing Your ExperiencedDetailFormModel Code

I spotted a syntax issue in your current code: the last [Prompt] attribute isn't closed, and you're missing the getter/setter for that final property. Also, if you want to collect skills directly in the form, you can add a dedicated property for that. Here's the corrected, expanded version:

[Serializable]
public class ExperiencedDetailFormModel
{
    [Prompt("Please enter your {&}")]
    public string EducationalQualification { get; set; }

    [Prompt("Please enter name of your {&}")]
    public string CurrentOrganization { get; set; }

    [Prompt("Please enter your {&}")]
    public string CurrentPositionInTheOrganization { get; set; }

    // Add this property to collect raw skill input (we'll process it into a list later)
    [Prompt("Please list your skills separated by commas (e.g., C#, Python, SQL)")]
    public string SkillsInput { get; set; }
}

Quick note: The {&} in the Prompt attribute automatically inserts the property's name into the prompt text, which keeps your code DRY and consistent.

2. Implementing String List Input in Bot Framework

There are three common, user-friendly ways to collect a list of skills (or any string list) from users—pick the one that fits your bot's flow best:

Option 1: Single Text Input with Delimiter

Ask users to enter all skills in one message separated by commas (or another delimiter), then split the input into a list. This works great for quick, straightforward input:

Example in a Waterfall Dialog

// Prompt the user for skills
private async Task<DialogTurnResult> GetSkillsStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    return await stepContext.PromptAsync(
        "textPrompt",
        new PromptOptions { Prompt = MessageFactory.Text("Please list your skills separated by commas (e.g., C#, Python, SQL)") },
        cancellationToken);
}

// Process the input into a list
private async Task<DialogTurnResult> ProcessSkillsStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var rawSkillsInput = (string)stepContext.Result;
    
    // Split, clean up whitespace, and remove empty entries
    List<string> userSkills = rawSkillsInput.Split(',')
                                        .Select(skill => skill.Trim())
                                        .Where(skill => !string.IsNullOrEmpty(skill))
                                        .ToList();
    
    // Save to your form model if needed
    var formModel = (ExperiencedDetailFormModel)stepContext.Options;
    formModel.SkillsInput = rawSkillsInput; // Store raw input, or track the list separately
    
    // Continue your dialog flow
    return await stepContext.NextAsync(userSkills, cancellationToken);
}

Option 2: Collect Skills One-by-One

If you want to guide users to enter skills individually (and let them stop when done), use a loop in your waterfall dialog:

Example Loop Flow

// Initialize list and prompt for first skill
private async Task<DialogTurnResult> CollectSingleSkillStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    if (!stepContext.Values.ContainsKey("UserSkills"))
    {
        stepContext.Values["UserSkills"] = new List<string>();
    }

    return await stepContext.PromptAsync(
        "textPrompt",
        new PromptOptions { Prompt = MessageFactory.Text("Enter one of your skills, or type 'done' when you're finished") },
        cancellationToken);
}

// Process each skill and loop until user says "done"
private async Task<DialogTurnResult> ProcessSingleSkillStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var skillInput = (string)stepContext.Result;
    var userSkills = (List<string>)stepContext.Values["UserSkills"];

    if (skillInput.Equals("done", StringComparison.OrdinalIgnoreCase))
    {
        if (userSkills.Count == 0)
        {
            await stepContext.Context.SendActivityAsync(MessageFactory.Text("You haven't entered any skills yet—let's try again!"), cancellationToken);
            return await stepContext.ReplaceDialogAsync(nameof(CollectSingleSkillStepAsync), null, cancellationToken);
        }
        // Move to next step with the full skills list
        return await stepContext.NextAsync(userSkills, cancellationToken);
    }
    else
    {
        userSkills.Add(skillInput.Trim());
        await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Added skill: {skillInput.Trim()}. Enter another or type 'done'."), cancellationToken);
        return await stepContext.ReplaceDialogAsync(nameof(CollectSingleSkillStepAsync), null, cancellationToken);
    }
}

Option 3: Use Adaptive Cards for Visual Input

For a more polished experience, use an Adaptive Card with multiple input fields. Users can fill in skills directly, and you can parse the submitted values into a list:

Example Adaptive Card (JSON)

{
    "type": "AdaptiveCard",
    "version": "1.0",
    "body": [
        {
            "type": "TextBlock",
            "text": "Tell us about your skills",
            "size": "Large",
            "weight": "Bolder"
        },
        {
            "type": "Input.Text",
            "id": "skill1",
            "placeholder": "Skill 1 (e.g., JavaScript)"
        },
        {
            "type": "Input.Text",
            "id": "skill2",
            "placeholder": "Skill 2 (optional)"
        },
        {
            "type": "Input.Text",
            "id": "skill3",
            "placeholder": "Skill 3 (optional)"
        }
    ],
    "actions": [
        {
            "type": "Action.Submit",
            "title": "Submit Skills"
        }
    ]
}

Parse Card Submission in Dialog

// Send the Adaptive Card to the user
private async Task<DialogTurnResult> GetSkillsViaCardStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var cardAttachment = new Attachment
    {
        ContentType = "application/vnd.microsoft.card.adaptive",
        Content = JsonConvert.DeserializeObject(/* Insert your Adaptive Card JSON string here */)
    };

    var promptOptions = new PromptOptions
    {
        Prompt = MessageFactory.Attachment(cardAttachment)
    };

    return await stepContext.PromptAsync("adaptiveCardPrompt", promptOptions, cancellationToken);
}

// Process the submitted card values into a list
private async Task<DialogTurnResult> ProcessCardSkillsStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var submittedValues = (IDictionary<string, object>)stepContext.Result;
    List<string> userSkills = new List<string>();

    // Collect non-empty skill inputs
    for (int i = 1; i <= 3; i++)
    {
        if (submittedValues.TryGetValue($"skill{i}", out var skillObj) && 
            skillObj is string skill && 
            !string.IsNullOrEmpty(skill.Trim()))
        {
            userSkills.Add(skill.Trim());
        }
    }

    // Use the skills list in your bot logic
    return await stepContext.NextAsync(userSkills, cancellationToken);
}

内容的提问来源于stack exchange,提问作者Akbar Badhusha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:17:45