I'm using bot framework version 4. I would like to access user state properties in the validator method but I didn't find any solution to it.
In the GitHub sample above, we have a validator AgePromptValidatorAsync
which validates age.
But I would want to access Name which I have stored in State property.
How could that be achieved.
And is it possible to access state/use GetAsync
in a method outside dialog which doesn't contain context.
@mdrichardson could you please help me in this.Thank you in advance.
UserProfile.Name
is saved before hitting validation.That sample doesn't do this on it's own, so you would:
private async Task<DialogTurnResult> NameConfirmStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["name"] = (string)stepContext.Result;
// ADDED: This code block saves the Name
if (!string.IsNullOrEmpty((string)stepContext.Result)) {
var userProfile = await _userProfileAccessor.GetAsync(stepContext.Context, () => new UserProfile(), cancellationToken);
userProfile.Name = (string)stepContext.Result;
await _userProfileAccessor.SetAsync(stepContext.Context, userProfile);
}
// We can send messages to the user at any point in the WaterfallStep.
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Thanks {stepContext.Result}."), cancellationToken);
// WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is a Prompt Dialog.
return await stepContext.PromptAsync(nameof(ConfirmPrompt), new PromptOptions { Prompt = MessageFactory.Text("Would you like to give your age?") }, cancellationToken);
}
// CHANGED: Since this accesses the userProfile, the method is no longer static. Also must be async
private async Task<bool> AgePromptValidatorAsync(PromptValidatorContext<int> promptContext, CancellationToken cancellationToken)
{
// ADDED: Here is how you can access the Name
// Note: You can use promptContext.Context instead of stepContext.Context since they're both ITurnContext
var userProfile = await _userProfileAccessor.GetAsync(promptContext.Context, () => new UserProfile(), cancellationToken);
var name = userProfile.Name;
// Do whatever you want with the Name
// CHANGED: Since this is now async, we don't return Task.FromResult(). We just return the result
return promptContext.Recognized.Succeeded && promptContext.Recognized.Value > 0 && promptContext.Recognized.Value < 150;
}
This is kind of possible, but you can't do this easily or out-of-the-box. There are some options that you can use, however (mostly in order from least difficult to most):
context
to whatever method/function you need to use it in. Just about every bot method you'd use has some kind of context that you can pass into another method. This is definitely your best option.