2017-03-17 41 views
2

我有以下的对话场景中僵尸:微软机器人框架:异常:在更改数据

  1. 发送短信给LUIS
  2. LUIS意图电话context.Call(...)推出一个对话框
  3. 此对话框终止时,保存在用户数据的一些信息:

    private static async Task storeBotData(IDialogContext context, BotData userData) { Activity activity = (Activity)context.Activity; StateClient sc = activity.GetStateClient(); await sc.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, userData); }

    并经过它会再次调用另一个对话框context.Call(...)

  4. 然后最后一个对话框运行并终止。

我的问题是,在第一个对话框的最终更新用户数据(步骤3)的时候,我在博特框架通道仿真器以下异常:

  `Exception: The data is changed [File of type 'text/plain']`... 

什么在这里发生?我认为当一个对话终止时,它自己调用setUserData,但我不明白为什么我不能在代码中的任何地方更新userData ...

我试图捕捉异常,但没有任何捕获..但我知道,用户数据被更新,因为当我尝试找回它回来了,它被更新......

欢迎任何帮助:)

感谢

+0

您正在使用哪个版本的框架? – Artem

回答

4

Botframework恢复/保存状态在每次活动之后的对话中,所以典型的流程如下所示:

[23:15:40] <- GET 200 getUserData 
[23:15:47] <- GET 200 getConversationData 
[23:15:47] <- GET 200 getPrivateConversationData 
... 
[23:16:42] <- POST 200 setConversationData 
[23:16:42] <- POST 200 setUserData 
[23:16:42] <- POST 200 setPrivateConversationData 

正如提到hereThese botData objects will fail to be stored if another instance of your bot has changed the object already.所以你的情况例外发生在对话结束时,当框架由他本人呼吁setUserData来,并计算出该BotData已经被改变(由您的BotState.SetUserDataAsync显式调用)。我想这就是为什么你无法赶上例外。

解决方案: 我用下面的代码,并将其固定的问题:

private static void storeBotData(IDialogContext context, BotData userData) 
{ 
     var data = context.UserData; 
     data.SetValue("field_name", false);    
} 

它的工作原理的原因是,我们修改的UserData的对象,但允许botFramework“落实”它自己,所以没有冲突

+0

谢谢@Artem,它完美的工作。您的权利,最好是将“提交”部分留给framewrok本身。 +1 – Ynnad

1

我同意@Artem(这也解决了我的问题,谢谢!)。我只想添加以下指南。

使用

var data = context.UserData; 
data.SetValue("field_name", false); 

,只要你有一个IDialogContext对象,所以你让机器人框架提交更改。

改用

StateClient sc = activity.GetStateClient(); 
await sc.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, userData); 

当你没有一个IDialogContext对象,例如在MessageController类中。