如何将用户上下文详细信息从bot Controller传递到FormDialog

时间:2018-04-19 13:21:41

标签: botframework

Bot Info

  • SDK平台:.NET
  • 有效频道:直线
  • 部署环境:Azure Bot服务

问题

如何将用户上下文详细信息从bot Controller传递到FormDialog?

代码示例

public virtual async Task < HttpResponseMessage > Post([FromBody] Activity activity) {
 if (activity != null && activity.GetActivityType() == ActivityTypes.Message) {
  await Conversation.SendAsync(activity, () => {
   return Chain.From(() => FormDialog.FromForm(RequestOrder.BuildEnquiryForm));
  });
 } else {
  HandleSystemMessage(activity);
 }
 return new HttpResponseMessage(System.Net.HttpStatusCode.OK);
}
public static IForm < RequestOrder > BuildEnquiryForm() {
 return new FormBuilder < RequestOrder > ()
  .Message("Hello {***Pass current user name?????****}Welcome to request bot!")
  .Field(nameof(IsTermsAgreed))
  .Field(nameof(ServiceRequired))
  .AddRemainingFields()
  .OnCompletion(ProcessParkingPermitRequest)
  .Message("Thank you, I have submitted your request.")
  .Build();
}

2 个答案:

答案 0 :(得分:1)

Fei Han的回答是正确的但是使用静态变量可能会导致一些意外错误,因为所有实例都共享相同的值。更好的方法是使用表单的状态。

请求订单

在RequestOrder类中,您需要添加一个新的成员变量username。

public class RequestOrder
{
     public string username;
     /* Rest of your member variables  */
}

.Message方法允许您访问表单的状态。您可以从表单状态获取用户名,如下所示:

 public static IForm < RequestOrder > BuildForm() 
 {
     return new FormBuilder < RequestOrder > ()
      .Message(async (state) => {
          return new PromptAttribute($"Hi {state.username}, Welcome to request bot! ");
       })
      .Field(nameof(IsTermsAgreed))
      .Field(nameof(ServiceRequired))
      .AddRemainingFields()
      .OnCompletion(ProcessParkingPermitRequest)
      .Message("Thank you, I have submitted your request.")
      .Build();
 }

根对话

在根对话框中,在调用BuildForm之前,您需要创建RequestOrder类的新实例,并将username初始化为当前用户的名称。然后使用FormOptions.PromptInStart选项将表单传递给BuildForm。

[Serializable]
public class RootDialog : IDialog<object>
{


    public Task StartAsync(IDialogContext context)
    {
        context.Wait(MessageReceivedAsync);

        return Task.CompletedTask;
    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
    { 
       var form = new RequestOrder()
       {
           username = context.Activity.From.Id
       };

       var requestOrderform = new FormDialog<RequestOrder>(form, RequestOrder.BuildForm, FormOptions.PromptInStart);
       context.Call<RequestOrder>(requestOrderform,  SampleFormSubmitted);
    }

    private async Task SampleFormSubmitted(IDialogContext context, IAwaitable<SampleForm> result)
    {
        try
        {
                var query = await result;
                context.Done(true);
        } 
        catch (FormCanceledException<SampleForm> e)
        {
                string reply;
                if (e.InnerException == null)
                {
                    reply = $"You quit. Maybe you can fill some other time.";
                }
                else
                {
                    reply = $"Something went wrong. Please try again.";
                }
                context.Done(true);
                await context.PostAsync(reply);
        }
    }
}

这就是你得到的:

enter image description here

答案 1 :(得分:0)

在下面的示例代码中,我使用字符串类型参数定义了SandwichOrder类的构造函数,然后从根对话框(而不是直接从Messages Controller)调用FormDialog作为子对话框,并将用户名作为参数传递,这对我有用,你可以参考它。

在RootDialog中:

[Serializable]
public class RootDialog : IDialog<object>
{
    public Task StartAsync(IDialogContext context)
    {
        context.Wait(MessageReceivedAsync);

        return Task.CompletedTask;
    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
    {
        var username = "Fei Han";

        var myform = new Microsoft.Bot.Builder.FormFlow.FormDialog<SandwichOrder>(new SandwichOrder($"{username}"), SandwichOrder.BuildForm, Microsoft.Bot.Builder.FormFlow.FormOptions.PromptInStart, null);

        context.Call<SandwichOrder>(myform, FormCompleteCallback);
    }

    private async Task FormCompleteCallback(IDialogContext context, IAwaitable<SandwichOrder> result)
    {
        await context.PostAsync($"The form is completed!");
        context.Done(this);
    }

}

在SandwichOrder课程中:

namespace BotFormFlowTest
{
    public enum SandwichOptions
    {
        BLT, BlackForestHam, BuffaloChicken, ChickenAndBaconRanchMelt, ColdCutCombo, MeatballMarinara,
        OvenRoastedChicken, RoastBeef, RotisserieStyleChicken, SpicyItalian, SteakAndCheese, SweetOnionTeriyaki, Tuna,
        TurkeyBreast, Veggie
    };
    public enum LengthOptions { SixInch, FootLong };
    public enum BreadOptions { NineGrainWheat, NineGrainHoneyOat, Italian, ItalianHerbsAndCheese, Flatbread };
    public enum CheeseOptions { American, MontereyCheddar, Pepperjack };
    public enum ToppingOptions
    {
        Avocado, BananaPeppers, Cucumbers, GreenBellPeppers, Jalapenos,
        Lettuce, Olives, Pickles, RedOnion, Spinach, Tomatoes
    };
    public enum SauceOptions
    {
        ChipotleSouthwest, HoneyMustard, LightMayonnaise, RegularMayonnaise,
        Mustard, Oil, Pepper, Ranch, SweetOnion, Vinegar
    };


    [Serializable]
    public class SandwichOrder
    {
        public static string username = "User";

        public SandwichOrder(string uname)
        {
            username = uname;
        }

        public SandwichOptions? Sandwich;
        public LengthOptions? Length;
        public BreadOptions? Bread;
        public CheeseOptions? Cheese;
        public List<ToppingOptions> Toppings;
        public List<SauceOptions> Sauce;

        public static IForm<SandwichOrder> BuildForm()
        {
            return new FormBuilder<SandwichOrder>()
                    .Message($"Hello {username}, Welcome to the simple sandwich order bot!")
                    .Build();
        }
    };
}

测试结果:

enter image description here