c# - Terminate all dialogs and exit conversation in MS Bot Framework when the user types "exit", "quit" etc -
i can't figure out how simple thing in ms bot framework: allow user break out of conversation, leave current dialogs , return main menu typing "quit", "exit" or "start over".
here's way main conversation set up:
public async task<httpresponsemessage> post([frombody]activity activity) { try { if (activity.type == activitytypes.message) { useractivitylogger.loguserbehaviour(activity); if (activity.text.tolower() == "start over") { //do here, don't have idialogcontext here! } botutils.sendtyping(activity); //send "typing" indicator upon each message received await conversation.sendasync(activity, () => new rootdialog()); } else { handlesystemmessage(activity); } }
i know how terminate dialog context.done<dialogtype>(this);
, in method, not have access idialogcontext object, cannot call .done()
.
is there other way terminate whole dialog stack when user types message, other adding check in each step of dialogs?
posted bounty:
i need way terminate idialog
s without using outrageous hack i've posted here (which deletes user data, need, e.g. user settings , preferences).
basically, when user types "quit" or "exit", need exit whatever idialog
in progress , return fresh state, if user has initiated conversation.
i need able messagecontroller.cs,
still not have access idialogcontext
. useful data seem have there activity
object. happy if points out other ways that.
another way approach find other way check "exit" , "quit" keywords @ other place of bot, rather in post method.
but shouldn't check done @ every single step of idialog
, because that's code , not possible (when using promptdialog
, have no access text user typed).
two possible ways didn't explore:
- instead of terminating current
idialog
s, start new conversation user (newconversationid
) - obtain
idialogstack
object , manage dialog stack.
the microsoft docs silent on object have no idea how it. not use chain
object allows .switch()
anywhere in bot, if think can rewritten use it, can 1 of ways solve too. however, haven't found how branching between various types of dialogs (formflow
, ordinary idialog
) in turn call own child dialogs etc.
problem breakdown
from understanding of question, want achieve reset dialog stack without destroy bot state.
facts (from read github repository)
- how framework save dialog stack below:
botdatastore > botdata > dialogstack
- botframework using autofac di container
- dialogmodule autofac module dialog components
how do
knowing facts above, solution be
- register dependencies can use in our controller:
// in global.asax.cs var builder = new containerbuilder(); builder.registermodule(new dialogmodule()); builder.registermodule(new reflectionsurrogatemodule()); builder.registermodule(new dialogmodule_makeroot()); var config = globalconfiguration.configuration; builder.registerapicontrollers(assembly.getexecutingassembly()); builder.registerwebapifilterprovider(config); var container = builder.build(); config.dependencyresolver = new autofacwebapidependencyresolver(container);
- get autofac container (feel free put anywhere in code you're comfortable with)
private static ilifetimescope container { { var config = globalconfiguration.configuration; var resolver = (autofacwebapidependencyresolver)config.dependencyresolver; return resolver.container; } }
- load botdata in scope
- load dialogstack
- reset dialogstack
- push new botdata botdatastore
using (var scope = dialogmodule.beginlifetimescope(container, activity)) { var botdata = scope.resolve<ibotdata>(); await botdata.loadasync(default(cancellationtoken)); var stack = scope.resolve<idialogstack>(); stack.reset(); await botdata.flushasync(default(cancellationtoken)); }
hope helps.
update 1 (27/08/2016)
thanks @ejadib point out, container being exposed in conversation class.
we can remove step 2 in answer above, in end code like
using (var scope = dialogmodule.beginlifetimescope(conversation.container, activity)) { var botdata = scope.resolve<ibotdata>(); await botdata.loadasync(default(cancellationtoken)); var stack = scope.resolve<idialogstack>(); stack.reset(); await botdata.flushasync(default(cancellationtoken)); }
Comments
Post a Comment