JsonReaderException: Error reading JArray using Adaptive Cards with Bot Framework

AdpativeCards should work well in the Bot. You should be able to produce great looking cards and also be able to respond to user input. In the latter case you are likely to run into a nasty little problem with how the serialization works with the Bot Framework and Adaptive Cards. If you’re struggling then there is a cheeky workaround;
The links starts at ~11mins into the whole tutorial https://youtu.be/2Hy9m5MvD4o?t=673

Advertisements

Gotcha with Bot Framework AutoSaveStateMiddleware and “long” flows

The AutoSaveStateMiddleware is a great addition to a Bot project. On every turn it can save the BotState objects you configure it to look after. Takes a way a lot of noise and accidentally forgetting to call save yourself. However, this is a little gotcha with this mechanism. Consider a classic Pizza ordering scenario;

  • USER – What pizzas do you have?
  • BOT – We have Vegetarian, Pepperoni, Ham & Cheese, Ham & Mushroom

From a Bot Framework perspective you might implement that as a series of Waterfall steps – potentially using a 3rd party service, i.e. potentially unreliable – slow;

  • Gather Available Ingredients For Location Step, NextAsync
  • Gather Available Pizza Recipes for Available Ingredients Step, NextAsync
  • Show Available Pizza Step

So far so good. Now, let’s say that before we started this Waterfall off we provided the user with a ‘See our drinks menu’ hero card button. What we expect to happen is that the drinks button will be shown before the potentially longer running food menu is processed and shown to the user. But what happens if the user presses that drinks button before the food menu has run through its steps and displayed its results? Well, something not so pleasant is the answer. Since the AutoSaveState will fire on the Turn, it won’t have fired until it prompts the user for their pizza choice. Therefore, even though the Drink button is in the same overall flow, the same activity, when the message is received by the bot it will NOT have an Active Dialog set in its context. This means that the message will NOT be passed onto what we think is our active dialog.

What solutions are there?

  • You can manually call the Save State, but it’s sort of a pain because that’s why we’re using the AutoSaveState
  • Simply ignore this issue. You may lose messages but the user will just try again
  • Use a base class for your dialogs that overrides NextAsync and saves the Dialog state

Upgrading your bot to .net core 2.2, warnings

When you upgrade your bot from .net core 2.0/2.1 to 2.2 you may see an warning that states; ‘A PackageReference to ‘Microsoft.AspNetCore.All’ specified a Version of 2.2.1. Specifying the version of this package is not recommended’.

To avoid this warning;

  1. Right click the bot project in the solution explorer and ‘unload’ it.
  2. Right click the unloaded project and edit it
  3. Change
    <PackageReference Include=”Microsoft.AspNetCore.All” Version=”2.2.1″/>
    To
    <PackageReference Include=”Microsoft.AspNetCore.All” />
  4. Reload the project.

 

Fetching all the LUIS intents in the Bot Framework

I decided that today was the day that I could no longer write a useful LUIS + Bot by only consuming the top scoring intent. So I checked the little Include all predicted intent scores switch in LUIS and ensured the ‘REST-API’ results had returned all the predictions. Yay. Changed my code to consume them to discover I was still only getting the top intent. Turns out you to do a little more work with the Bot SDKs to see the other intents;

v3 SDK

In your code that implements the LUISDialog base class;

protected override LuisRequest ModifyLuisRequest(LuisRequest request)
{
request.Verbose = true;
return base.ModifyLuisRequest(request);
}

v4 SDK

In the code where you create your LUIS Application and Recognizer, add the IncludeAllIntents options;

var app = new LuisApplication(luis.AppId, luis.AuthoringKey, luis.GetEndpoint());
var recognizer = new LuisRecognizer(

app,

new LuisPredictionOptions { IncludeAllIntents = true });

botframeworkoptions.state is obsolete

An recent update to the Bot Framework means that you may see some obsolete messages when trying to add conversation/user state, etc. to the options object in the setup. Don’t worry, it’s easy enough to alter.

...
// Create and add conversation state.
var conversationState = new ConversationState(dataStore);
// REMOVE THIS -> options.State.Add(conversationState);
services.AddSingleton(conversationState);
...

Introduction to writing Bot Application video tutorial

Introduction to the tutorial series is about writing bot applications using the Microsoft Bot Framework v4. The goal of this tutorial is to help someone who is interested in writing a Bot application that may not have much experience in software development. It will be a, “warts and all” journey to show how I would develop a bot. So I will be making mistakes and showing you how I go about resolving them. It will get you to a point where you can write your own conversational bot and provide you with some of the additional tools to help you resolve issues that you may find.

Introduction

Ep1 Setup

Ep2 Bot Basics

Ep3 Language Understanding

Ep4 Bot & LUIS

Ep5a Dialogs

Ep5b Dialogs

Ep6 Wrap up

Get Sentiment Score from LUIS RecognizerResult

Another quick extension method to help with getting a sentiment score from a RecognizerResult;

public static double? GetSentimentScore(this RecognizerResult luisResult)
{
    double? result = null;

    if (luisResult != null)
    {        
        var data = luisResult.Properties["sentiment"];
        var sentimentValues = data as IDictionary;
        var score = sentimentValues["score"] as JValue;
        result = (double)score.Value;
    }

    return result;
}