2017-05-09 11 views
0

私は1つのBOTアプリケーションを開発しました。ここでフォームフローを使用して、一連の質問をユーザーに求めました。今私は、ユーザーが無効なオプションを3回以上入力するとイベントをキャプチャする必要があります。私は、PromptDialogのTooManyAttemptsExceptionクラスを見つけましたが、FormDialogで同じものを見つけることができませんでした。あまりにも多くの試行をキャプチャし、ユーザーがFormDialogでさらに試行を停止する方法はありますか?Microsoft Bot:フォームフローで多すぎる試行をキャプチャする方法?

//サンプルコードTooManyAttemptsExceptionをスローしませんFormFlow

{ 
    var enrollmentForm = new FormDialog<AppointmentQuery>(new Models.AppointmentQuery(), AppointmentForm.BuildForm, FormOptions.PromptInStart); 
         context.Call<AppointmentQuery>(enrollmentForm, this.ResumeAfterOptionDialog); 

    private async Task ResumeAfterOptionDialog(IDialogContext context, IAwaitable<AppointmentQuery> result) 
    { 
     try 
     { 
      var message = await result; 
     } 
     catch (FormCanceledException e) 
     { 
      string reply = string.Empty; 
      await this.StartOverAsync(context, reply); 
     } 
     catch (TooManyAttemptsException et) 
     { 
      await context.PostAsync($"Ooops! Too many attemps :(. But don't worry, I'm handling that exception and you can try again!"); 
      await this.StartOverAsync(context, ""); 
     } 

     catch (Exception ex) 
     { 
      await context.PostAsync($"Failed with message: {ex.Message}"); 
     } 
     finally 
     { 
      context.Wait(this.MessageReceivedAsync); 
     } 
    } 
} 

答えて

0

versionAttemptsフィールドがprivate staticあるか

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" 
      }; 
     } 
    } 
} 

は注意:ただし、この問題を回避するには、このような独自のフィールド検証を実行することです。次に、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); 
     } 
    } 
} 

お知らせPostFormCanceledExceptionハンドラ、TooManyAttemptsExceptionが発生したときにあなたが知ることができ、when(fcEx.InnerException is TooManyAttemptsException)を使用。面白いことに、FormCanceledExceptionは、完了したフィールドに関する詳細情報を提供し、例外時のフォームの状態に関する詳細情報を提供します。

このコードは、BotDemos GitHubリポジトリのBugFormFlowBot2プロジェクトにあります。

+0

ありがとうございます。あなたのケースでは "バージョン"フィールドは文字列なので、ユーザーがこのフィールドに任意のputを渡すと、validateメソッドが呼び出されます。私の場合、フィールドはEnum型です。したがって、 "validate:"メソッドが呼び出されていない場合は、エラーメッセージが直接表示されます。あらかじめ定義されたオプションがあるEnum型フィールドの場合、validateメソッドは呼び出されません。 – user1899731

+0

これは私の列挙型フィールドです。[Template(TemplateUsage.NotUnderstood、 "私は理解できません\" {0} \ "、"再試行、\ "{0} \"を取得しません。])]) public CustomerTypeOptions?顧客タイプ;私はテンプレートメッセージを直接取得します – user1899731

関連する問題