问题
I am using BotBuilder SDK v4. Here is the explanation below (ignoring some extra code).
On my bot's OnTurnAsync
I am calling one of my dialog like so.
public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
var state = await _accessors.TurnStateAccessor.GetAsync(turnContext, () => new TurnState()).ConfigureAwait(false);
var dialogContext = await _dialogs.CreateContextAsync(turnContext).ConfigureAwait(false);
await dialogContext.BeginDialogAsync(nameof(SomeDialog)).ConfigureAwait(false);
//remaining code..
}
The call is successfull and it reaches the dialog. Below is the code.
public override Task<DialogTurnResult> BeginDialogAsync(DialogContext outerDc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
{
outerDc.ContinueDialogAsync();
return base.BeginDialogAsync(outerDc, options, cancellationToken);
}
public override Task<DialogTurnResult> ContinueDialogAsync(DialogContext outerDc, CancellationToken cancellationToken = default(CancellationToken))
{
var turnState = outerDc.Context.TurnState["ConversationState"]; //access turn state here
outerDc.EndDialogAsync();
return base.ContinueDialogAsync(outerDc, cancellationToken);
}
Inside ContinueDialogAsync
I am trying to access the dialog's context object outerDc
which contains my bot's state data, as I configured and see in the immediate/watch window.
outerDc.Context.TurnState Count = 3
[0]: {[BotIdentity, System.Security.Claims.ClaimsIdentity]}
[1]: {[Microsoft.Bot.Connector.IConnectorClient, Microsoft.Bot.Connector.ConnectorClient]}
[2]: {[ConversationState, Microsoft.Bot.Builder.BotState+CachedBotState]} outerDc.Context.TurnState["ConversationState"] {Microsoft.Bot.Builder.BotState.CachedBotState}
Hash: "{}"
State: Count = 2
Here is the QuickWatch expression and the highlighted value is exactly what I need.
When I try to use the expression ((Microsoft.Bot.Builder.BotState.CachedBotState)outerDc.Context.TurnState["ConversationState"]).State
in my code, it seems CachedBotState
is not part of the namespace/package. Also it seems that Microsoft.Bot.Builder.BotState.CachedBotState
is part of the Microsoft.Bot.Builder.Core
nuget package which is still in preview stage.
I know I can pass the TurnState
object as an additional parameter from the OnTurnAsync
to my dialog. But, I want to access it through the dialog's context, when it shows it is already there. Is there a way to do that?
Please let me know if I can elaborate more.
回答1:
First, CachedBotState
is an internal implementation detail and not something you should ever be expecting to use. Likewise you really shouldn't be digging into the TurnState
and expecting to work with values inside of there which are not under your control as it's also just an implementation detail of how the bot state maintains values for the scope of the turn. I would recommend you abandon this approach because, ultimately, the whole implementation could change in the next version (since it's internal details and not subject to semver rules) and then your code would break as a result.
Instead, what you should be doing is passing your IStatePropertyAccessor<TurnState>
through to the constructor of the SomeDialog
as you're creating it and adding it to the DialogSet
. This gives SomeDialog
the ability to read/write that particular property for a given turn and your code would change to look like this instead:
public override Task<DialogTurnResult> ContinueDialogAsync(DialogContext outerDc, CancellationToken cancellationToken = default(CancellationToken))
{
// Access state via the property accessor rather than trying to access raw internals of bot state management
var turnState = await _turnStatePropertyAccessor.GetAsync(outerDc.Context);
outerDc.EndDialogAsync();
return base.ContinueDialogAsync(outerDc, cancellationToken);
}
来源:https://stackoverflow.com/questions/54535119/getting-turnstate-data-from-dialogcontext