How to handle exception in chatbot using Microsoft Bot Framework. I am getting the exception below since I have given a wrong LUIS subscripion key but I would like to handle the exception and provide a custom message instead of the below one!
NoResumeHandlerException: IDialog method execution finished with no resume handler specified through IDialogStack.
Here is the code follows of the MessageController..
if (activity.Type == ActivityTypes.Message)
{
//await Microsoft.Bot.Builder.Dialogs.Conversation.SendAsync(activity, () => new ContactOneDialog());
//Implementation of typing indication
//ConnectorClient connector = new ConnectorClient(new System.Uri(activity.ServiceUrl));
//Activity isTypingReply = activity.CreateReply("Shuttlebot is typing...");
//isTypingReply.Type = ActivityTypes.Typing;
//await connector.Conversations.ReplyToActivityAsync(isTypingReply);
logger.Debug("The User's local timeStamp is: " + activity.LocalTimestamp + "and service timeStamp is: " + activity.Timestamp);
await Conversation.SendAsync(activity, () =>
new ExceptionHandlerDialog<object>(new ShuttleBusDialog(), displayException: true));
}
else
{
HandleSystemMessage(activity);
}
Related
Attaching the code snippet below. UniversalBot and ChatConnector has been deprecated in botbuilder 4.1.5.
var bot;
try {
bot = new BasicBot(conversationState, userState, botConfig);
} catch (err) {
console.error(`[botInitializationError]: ${ err }`);
process.exit();
}
// Create HTTP server
// let server = restify.createServer();
let server = express();
server.listen(process.env.port || process.env.PORT || 3978, function() {
console.log(`\n${ server.name } listening to ${ server.url }`);
console.log(`\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator`);
console.log(`\nTo talk to your bot, open basic-bot.bot file in the Emulator`);
});
// Listen for incoming activities and route them to your bot main dialog.
server.post('/api/messages', (req, res) => {
// Route received a request to adapter for processing
adapter.processActivity(req, res, async (turnContext) => {
// route to bot activity handler.
await bot.onTurn(turnContext);
});
});
Your question is fairly general.
The session object from 3.x has been removed. Instead acccessors are used. You will want to do following in the bot class:
public onTurn = async (turnContext: TurnContext) => {
const userProfile = await this.userProfile.get(turnContext, new UserProfile());
const conversationData = await this.dialogStateAccessor.get(turnContext, { dialogStack: undefined });
// set vars in cache
userProfile.yourUserVarProp = "userValue";
conversationData.yourConversationVarProp = "conversationValue";
// persist userVars through dialog turn
await this.userProfile.set(turnContext, userProfile);
// persist conversationVars through dialog turn
await this.dialogStateAccessor.set(turnContext, conversationData);
//
// -> your dialogs here (await dc.beginDialog("dialogname");)
//
// save uservars to db at end of a turn
await this.userState.saveChanges(turnContext);
// save conversationVars to db at end of a turn
await this.conversationState.saveChanges(turnContext);
}
But there is some additional constructor stuff
#param {ConversationState} conversationState A ConversationState object used to store the dialog state.
#param {UserState} userState A UserState object used to store values specific to the user.
... and creating the userProfile and dialogStateAccessor itself.
For the whole picture have better a look at https://github.com/Microsoft/BotBuilder-Samples/tree/master/samples/javascript_nodejs .
Or try the generator: https://learn.microsoft.com/en-us/azure/bot-service/javascript/bot-builder-javascript-quickstart?view=azure-bot-service-4.0.
I'm developing a bot using the bot framework for node.js v4. Imagine the following scenario:
user: Hello
bot: How can I help you?
user: What is the deadline for completing the transfer?
bot: What is the value of the transfer?
user: $ 5,000
At this time, I am executing the textprompt to request the value of the transfer and I need to validate if the user entity ($ 5,000) has been identified as the money entity.
This is the dialog stack:
this.addDialog(new WaterfallDialog(DUVIDA_NIVEL_APROVACAO_DIALOG, [
this.initializeStateStep.bind(this),
this.moneyStep.bind(this),
this.captureMoney.bind(this),
this.endConversation.bind(this)
]));
this.addDialog(new TextPrompt(MONEY_PROMPT, this.validateMoneyInput));
And the validate method:
async validateMoneyInput(validatorContext) {
const value = validatorContext.recognized.value; //how to get entities?
if (value == 'money') {
return VALIDATION_SUCCEEDED;
} else {
await validatorContext.context.sendActivity(`What is the value of the transfer?`);
return VALIDATION_FAILED;
}
}
However, in the callback to validate the textprompt, I have only the text sent by the user.
How can I get the entities extracted by Luis within the textprompt validation method?
To get any LUIS results into the dialog waterfall, you first need to capture the results on the turnContext, like so:
if (turnContext.activity.type === ActivityTypes.Message) {
// Returns LUIS matched results
const results = await this.luisRecognizer.recognize(turnContext);
// Results are assigned to the turnContext object and is passed into the dialog stack
turnContext.topIntent = results.luisResult.topScoringIntent;
turnContext.topIntent.entities = results.luisResult.entities;
turnContext.topIntent.value = results.luisResult.query;
// Create a dialog context object.
const dc = await this.dialogs.createContext(turnContext);
const utterance = (turnContext.activity.text || '').trim().toLowerCase();
if (utterance === 'cancel') {
if (dc.activeDialog) {
await dc.cancelAllDialogs();
await dc.context.sendActivity(`Ok... canceled.`);
} else {
await dc.context.sendActivity(`Nothing to cancel.`);
}
}
// If the bot has not yet responded, continue processing the current dialog.
await dc.continueDialog();
// Start the sample dialog in response to any other input.
if (!turnContext.responded) {
await dc.beginDialog(DUVIDA_NIVEL_APROVACAO_DIALOG);
}
}
Now that the results have been passed in, you can access the results via the step.context object, like so:
this.dialogs.add(new TextPrompt(MONEY_PROMPT, this.validateMoneyInput.bind(this)));
async moneyStep(step) {
await step.prompt(MONEY_PROMPT, `What is the value of the transfer?`,
{
retryPrompt: 'Try again. What is the value of the transfer?'
}
);
}
async validateMoneyInput(step) {
// LUIS results passed into turnContext are retrieved
const intent = step.context.topIntent['intent'];
const entity = step.context.topIntent.entities;
console.log(entity);
// Validation based on matched intent
if (intent == 'Money') {
return await step.context.sendActivity('Validation succeeded');
} else if (intent != 'Money') {
return await step.context.sendActivity('Validation failed');
}
}
I also assigned the entities value to a variable for accessing since you were asking about it.
Hope of help!
I'm working on a simple Ethereum project, but since I'm not certain whether the issue I'm having is to do with Web3 or Async/Await, I decided to post this question to both Stackoverflow and Ethereum Stackexchange. I'm using javascript with Web3 for this project.
Essentially, I'm running with three async functions, one of which is meant to call the others before performing some calculations and returning the results of its efforts:
async function getFounder() {
console.log("getFounder method");
try{
console.log("just before whoIsFounder");
whoIsFounder = await promisify(RegionalContract2.getFounder);
}catch(err) {
console.log(err)
}
console.log("This Election's Founder is : " + whoIsFounder);
return whoIsFounder;
}
async function getCurrentAccount(){ <<<<<<The problem method
console.log("getCurrentAccount method");
currentAccount = await web3.eth.getAccounts();
return currentAccount;
}
async function isItYours(){
try{
console.log("Inside the isItYours method");
currentAccount = await getCurrentAccount();
founder = await getFounder();
console.log("The getFounder method has resolved completely");
console.log("founder is " + founder);
if (founder != null){
if (founder === currentAccount) {//if the Founder is the same as the value entered.
alert("You are in fact the owner of this Election.");
var x = document.getElementById("hidden");
x.style.display = "block";
}
else {
alert("You are NOT the owner of this Election. The value sent in was " + currentAccount);
}
}
else {
alert("Founder can't be null. Either you're not logged into Metamask, or your account somehow isn't linked up properly.");
}
}catch (err) {
console.log(err)
}
}
isItYours();
When I tried to run this code, however, I got the following error:
Uncaught TypeError: e is not a function
at inpage.js:1
at inpage.js:1
at inpage.js:1
at inpage.js:1
at i (inpage.js:1)
at inpage.js:1
at inpage.js:1
at u (inpage.js:1)
at s (inpage.js:1)
at inpage.js:1
The full console log is:
The founder is:
inpage.js:1 null "0x59a09d00eb11caa5fa70484bf4d78015d10938bc"
admin.html:340 Inside the isItYours method
admin.html:331 getCurrentAccount method
admin.html:305 getFounder method
admin.html:318 just before whoIsFounder
***the aforementioned error from the previous segment***
This Election's Founder is : 0x59a09d00eb11caa5fa70484bf4d78015d10938bc
admin.html:344 The getFounder method has resolved completely
admin.html:345 founder is 0x59a09d00eb11caa5fa70484bf4d78015d10938bc
This leads me to think that the problem lies with getCurrentAccount(), since it employs web3.eth.getAccounts(), rather than a custom method, to return its value. Does anyone know why this might be happening? Thanks.
We are using the Microsoft Bot Framework for our chat bot. Our Message Controller is standard :
public async Task<HttpResponseMessage> Post([FromBody] Activity activity)
{
HttpResponseMessage response;
try
{
if (activity.Type == ActivityTypes.Message)
{
//do some stuff
await Conversation.SendAsync(activity, () => new RootDialog());
}
else
{
HandleSystemMessage(activity);
}
response = this.Request.CreateResponse(HttpStatusCode.OK);
}
catch (Exception ex)
{
//do some catching
}
return response;
}
Sometimes, the bot needs to have long monologs. If it takes too long, we receive a 502 Bad Gateway error.
Any solution for that ?
Bot Framework calls time out after 15 seconds. Your bot must return a successful HTTP status code within 15 seconds for Direct Line to consider the message successfully sent.
If your bot does a lot of offline work or sends multiple messages, you should move that work to a background thread so the incoming request completes within 15 seconds.
Here's a snippet that correctly handles loads hosted inside ASP.Net and other hosting environments.
if (HostingEnvironment.IsHosted)
{
HostingEnvironment.QueueBackgroundWorkItem(c => DoWorkAsync());
}
else
{
Task.Run(() => DoWorkAsync());
}
...
private async Task DoWorkAsync()
{
// do some stuff
}
Task.Run is simpler but HostingEnvironment.QueueBackgroundWorkItem prevents ASP.Net from tearing down your process before this work is complete.
I have gone through many tutorials to get the method below working but when it is executed, the app hangs forever because the method never finishes.
PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync
The method does not throw any exceptions and I cant debug the cause either, I'm not sure what I'm doing wrong so please correct me on my code and app capabilities. Thanks.
Notification Initialization Method:
private async Task InitNotificationsAsync()
{
try
{
Constants.NotificationChannel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
Constants.NotifyHub = new NotificationHub("hub name", "access key");
Constants.NotificationHubRegistration = await Constants.NotifyHub.RegisterNativeAsync(Constants.NotificationChannel.Uri);
if (!(Constants.NotificationHubRegistration != null) || !(Constants.NotificationHubRegistration.RegistrationId != null)) await new MessageDialog("Microsoft Azure Push Notification Services are unavailable!", "Problem!?").ShowAsync();
} catch (Exception e)
{
await new MessageDialog("Microsoft Azure Push Notification Services are unavailable!\n\n" + e.Message, "Problem!?").ShowAsync();
}
}
App Capabilities:
Internet (Client & Server)
Internet (Client)
Location
User Account Information