FormFlow不會拋出TooManyAttemptsException
。然而,一個解決方法是這樣執行自己的場驗證:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Microsoft.Bot.Builder.FormFlow;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.FormFlow.Advanced;
using System.Threading.Tasks;
namespace BugFormFlowBot2
{
[Serializable]
[Template(TemplateUsage.EnumSelectOne, "Which {&} were you working with? {||}")]
[Template(TemplateUsage.EnumSelectMany, "Which {&} were you working with? {||}", ChoiceStyle = ChoiceStyleOptions.PerLine)]
public class BugReport
{
public string Product { get; set; }
public string Version { get; set; }
public List<PlatformOptions> Platform { get; set; }
[Prompt("What is the {&}")]
[Describe("Description of the Problem")]
public string ProblemDescription { get; set; }
[Numeric(1, 3)]
public int Priority { get; set; }
private static int versionAttempts = 0;
public static IForm<BugReport> BuildForm()
{
return new FormBuilder<BugReport>()
.Message("Welcome to Bug Report bot!")
.Field(new FieldReflector<BugReport>(nameof(Product))
.SetType(null)
.SetDefine((state, field) =>
{
foreach (var prod in GetProducts())
field
.AddDescription(prod, prod)
.AddTerms(prod, prod);
return Task.FromResult(true);
}))
.Field(nameof(Version),
validate: async (state, response) =>
{
var result = new ValidateResult { IsValid = true, Value = response };
foreach (var segment in (response as string ?? "").Split('.'))
{
int digit;
if (!int.TryParse(segment, out digit))
{
result.Feedback =
"Version number must be numeric segments, optionally separated by dots. e.g. 7.2, 10, or 3.56";
result.IsValid = false;
if (++versionAttempts > 2)
throw new TooManyAttemptsException("Too many attempts at the version number.");
break;
}
}
return await Task.FromResult(result);
})
.Field(nameof(Platform))
.AddRemainingFields()
.Confirm(async (bugReport) =>
{
var response = new PromptAttribute(
$"You entered {bugReport.Product}, {bugReport.Version}, {bugReport.Platform}" +
$"{bugReport.ProblemDescription}, {bugReport.Priority}. Is this Correct?");
return await Task.FromResult(response);
})
.OnCompletion(async (context, bugReport) =>
{
await context.PostAsync("Thanks for the report!");
})
.Build();
}
static List<string> GetProducts()
{
return new List<string>
{
"Office",
"SQL Server",
"Visual Studio"
};
}
}
}
通知之versionAttempts
場是如何private static
。然後查看Version
字段的驗證以及它如何拋出TooManyAttemptsException
。
這並不能完全解決問題,因爲FormFlow將所有異常包裝在FormCanceledException
中。以下代碼顯示瞭如何處理。
using System;
using System.Threading.Tasks;
using System.Web.Http;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.FormFlow;
using System.Net.Http;
using System.Net;
namespace BugFormFlowBot2
{
[BotAuthentication]
public class MessagesController : ApiController
{
internal static IDialog<BugReport> MakeRootDialog()
{
return Chain.From(() => FormDialog.FromForm(BugReport.BuildForm))
.Loop();
}
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity?.Type == ActivityTypes.Message)
try
{
await Conversation.SendAsync(activity, MakeRootDialog);
}
catch (FormCanceledException fcEx) when(fcEx.InnerException is TooManyAttemptsException)
{
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity reply = activity.CreateReply(
$"Too Many Attempts at {fcEx.Last}. " +
$"Completed Steps: {string.Join(", ", fcEx.Completed)}");
await connector.Conversations.ReplyToActivityAsync(reply);
}
catch (FormCanceledException fcEx)
{
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity reply = activity.CreateReply(
$"Form cancelled at {fcEx.Last}. " +
$"Completed Steps: {string.Join(", ", fcEx.Completed)}");
await connector.Conversations.ReplyToActivityAsync(reply);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
}
}
通知的FormCanceledException
處理程序Post
,使用when(fcEx.InnerException is TooManyAttemptsException)
,讓您知道TooManyAttemptsException
時有發生。有趣的是,FormCanceledException
提供了有關已完成的字段的更多信息,從而爲您提供有關異常時表單狀態的更多信息。
您可以在我的BotDemos GitHub存儲庫的BugFormFlowBot2項目中找到此代碼。
感謝您的建議。在你的情況「Version」字段是字符串,所以當用戶給這個字段的任何放,驗證方法被調用。在我的情況下,該字段是Enum類型。所以「validate:」方法根本不被調用,而是直接給出錯誤信息。對於那裏有預定義選項的枚舉類型字段,驗證方法沒有被調用。 – user1899731
這是我的枚舉字段[提示(「您是現有客戶嗎?{||}」,ChoiceFormat =「{1}」)] [模板(TemplateUsage.NotUnderstood,「我不明白\」{0} \ 「。」,「再試一次,我不會得到\」{0} \「。」)] public CustomerTypeOptions?客戶類型;我直接獲取模板消息 – user1899731