BotFramework WebChat v4:JS向C# Bot回传位置信息报错求助
解决Web Chat v4回传位置信息到Bot Framework机器人的异常问题
我来帮你排查下这个问题!从你的代码来看,触发异常的核心原因大概率是store的作用域限制以及发送活动的参数不完整,咱们一步步来修正:
1. 修复store作用域问题
你定义的showPosition是全局函数,而store变量可能处于局部作用域(比如DOM加载完成的回调里),导致showPosition无法正确调用store.dispatch。解决方法是把showPosition放到store定义的同一作用域内,利用闭包直接访问dispatch:
const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => { // 把showPosition定义在store作用域内,直接访问dispatch function showPosition(position) { console.log(`Latitude: ${position.coords.latitude} Longitude: ${position.coords.longitude}`); const locationValue = `${position.coords.latitude};${position.coords.longitude}`; // 用dispatch发送消息,避免store作用域问题 dispatch({ type: 'WEB_CHAT/SEND_MESSAGE_BACK', payload: { text: locationValue, value: locationValue, // 关键:必须关联触发此操作的原始event活动ID activityId: action.payload.activity.id } }); } if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') { const activityOut = action.payload.activity; if (activityOut.type === 'message') { return next(action); } if (activityOut.type === 'event') { if (activityOut.name === 'getLocation') { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition); } else { console.log("Geolocation is not supported by this browser."); } } return next(action); } } else if (action.type === 'DIRECT_LINE/POST_ACTIVITY') { return next(action); } else { return next(action); } });
2. 更推荐的方式:直接发送Event活动回传
既然机器人是通过event类型活动触发位置获取,回传event类型活动会让业务逻辑更清晰,也更容易在C#端处理。你可以替换成DIRECT_LINE/POST_ACTIVITY来发送:
const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => { function showPosition(position) { const locationValue = `${position.coords.latitude};${position.coords.longitude}`; dispatch({ type: 'DIRECT_LINE/POST_ACTIVITY', payload: { activity: { type: 'event', name: 'locationReceived', // 自定义事件名,和机器人端约定 value: locationValue, from: { id: chatUser.id, name: chatUser.name }, locale: 'fr-FR' } } }); } // 其余原有逻辑不变... });
对应的C#机器人端处理代码:
protected override async Task OnEventActivityAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken) { if (turnContext.Activity.Name.Equals("locationReceived", StringComparison.OrdinalIgnoreCase)) { var locationData = turnContext.Activity.Value.ToString(); // 这里处理位置信息,比如解析经纬度、存储等 await turnContext.SendActivityAsync(MessageFactory.Text($"已收到你的位置信息:{locationData}"), cancellationToken); } await base.OnEventActivityAsync(turnContext, cancellationToken); }
3. 备选方案:直接使用DirectLine实例发送
如果你觉得通过store处理太复杂,也可以直接保存DirectLine实例,在showPosition里调用postActivity:
// 提前保存DirectLine实例 const directLine = window.WebChat.createDirectLine({ secret: 'your-secret-token' }); // 定义showPosition时直接使用directLine function showPosition(position) { const locationValue = `${position.coords.latitude};${position.coords.longitude}`; directLine.postActivity({ type: 'message', text: locationValue, from: { id: chatUser.id, name: chatUser.name } }).subscribe( activityId => console.log(`位置消息已发送,ID:${activityId}`), error => console.error('发送位置失败:', error) ); } // 渲染WebChat时传入directLine window.WebChat.renderWebChat( { directLine, store, userID: chatUser.id, username: chatUser.name, locale: 'fr-FR', styleOptions }, document.getElementById('BotChatGoesHere') );
关键注意点
- 确保
chatUser.id和WebChat初始化时的userID一致,避免身份不匹配 - 如果浏览器有位置权限限制,要先引导用户授权,否则
getCurrentPosition会失败 - 检查WebChat版本,确保使用的v4版本支持你调用的action类型(建议使用最新稳定版)
内容的提问来源于stack exchange,提问作者Shamrock
相关产品推荐
相关产品推荐

