Reputation: 1
I'm trying to implement a custom authentication on my bot as described in the Pattern A of this article. However, the data that my WebApplication is trying to write to my BotStateDataStore is not being persisted on it and consequently not available when I try to read it from the bot itself.
Key points:
I've just created a new asp.net web application on the same solution of my bot, set the same MicrosoftAppId and MicrosoftAppPassword used on de bot Web.Config and implemented the following method on a new Controller in order to try to persist :
public class AuthenticationController : ApiController
{
// GET: api/Authentication
[HttpGet]
public async Task<bool> Authorize(string token)
{
try
{
var appId = ConfigurationManager.AppSettings["MicrosoftAppId"];
var password = ConfigurationManager.AppSettings["MicrosoftAppPassword"];
var botCred = new MicrosoftAppCredentials(appId, password);
var stateClient = new StateClient(botCred);
BotData botData = new BotData(eTag: "*");
//Suppose I've just called an internal service to get the profile of my user and got it's profile:
//Let's save it in the botstate to make this information avalilable to the bot cause I'll need it there in order to choose different Dialogs withing the bot depending on the user's profile (Anonimous, Identificado, Advanced or Professional)
botData.SetProperty<string>('Profile', "Identificado");
var data = await stateClient.BotState.SetUserDataAsync("directline", "User1", botData);
return true;
}
catch (Exception ex)
{
return false;
}
}
}
The problem is that, despide of the code above is getting executed without any exception, when I try to get the "profile" value inside the bot as demonstrated in the code below, the
context.UserData.TryGetValue<string>(stateKey, out perfil)
returns null
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
try
{
context.UserData.SetValue<string>("Perfil", "XXXXXXXXX");
string perfil;
if (context.UserData.TryGetValue<string>(stateKey, out perfil))
{
await context.PostAsync($"Olá, fulano o seu perfil é '{perfil}'");
}
else
{
await context.PostAsync($"Olá, anônimo");
}
}
catch (Exception ex)
{
throw ex;
}
if (message.Text == null || message.Text.Equals(GlobalResources.Back, StringComparison.InvariantCultureIgnoreCase))
{ //Quando entra nesse diálogo a 1ª vez ou volta de um dialogo filho.
var rootCard = GetCard();
var reply = context.MakeMessage();
reply.Attachments.Add(rootCard);
await context.PostAsync(reply);
context.Wait(MessageReceivedAsync);
}
else if (message.Text.Equals(GlobalResources.AboutToro, StringComparison.InvariantCultureIgnoreCase))
{
context.Call(new AboutToroDialog(), OnResumeToRootDialog);
}
else
{
var messageToForward = await result;
await context.Forward(new QnADialog(), AfterFAQDialog, messageToForward, CancellationToken.None);
return;
}
}
Can anyone please, tell me how can I write some value from a asp.net web MVC application in the botStateStore of my bot, witch is another botframework (Asp.Net.WebApi) application ?
Upvotes: 1
Views: 127
Reputation: 8292
context.UserData
will use the custom state client you've implemented.
var stateClient = new StateClient(botCred);
will use the default state client. If you want to use the state client you've implemented outside of a dialog, then create an instance of it directly (the one you've implemented) and use that.
Edit:
There is currently no method for forcing the StateClient use a custom IBotDataStore. However, you can just create the IBotDataStore implementation and use it directly. Here's an example of using a custom IBotDataStore implementation outside of a dialog: (this is based on https://blog.botframework.com/2017/07/26/Saving-State-Sql-Dotnet/ )
var store = new SqlBotDataStore("BotDataContextConnectionString") as IBotDataStore<BotData>;
var address = new Address()
{
BotId = activity.Recipient.Id,
ChannelId = activity.ChannelId,
ConversationId = activity.Conversation.Id,
ServiceUrl = activity.ServiceUrl,
UserId = activity.From.Id
};
var botData = await store.LoadAsync(address, BotStoreType.BotUserData, new System.Threading.CancellationToken());
var dataInfo = botData.GetProperty<BotDataInfo>(BotStoreType.BotUserData.ToString()) ?? new BotDataInfo();
dataInfo.Count++;
botData.SetProperty(BotStoreType.BotUserData.ToString(), dataInfo);
await store.SaveAsync(address, BotStoreType.BotUserData, botData, new System.Threading.CancellationToken());
Upvotes: 1