You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Azure的Bot Framework聊天机器人:Express后端对接Directline API v3.0的AJAX交互问题

Hey there! Let's break down how to get AJAX-based Activity send/receive working for your setup—you're already on the right track by handling session generation backend-side, which is the secure way to do it. Here's a step-by-step guide with code examples tailored to your stack:

1. First, Validate Your Backend Session ID Generation

First, let's confirm your Express endpoint for generating Direct Line conversations is set up correctly. This endpoint will return a conversationId and token that your frontend uses to communicate with the bot:

const express = require('express');
const axios = require('axios');
const cors = require('cors'); // Optional, but useful if frontend is on a different port
const app = express();
const port = process.env.PORT || 3000;

// Store these in environment variables (never hard-code secrets!)
const DIRECT_LINE_SECRET = process.env.DIRECT_LINE_SECRET;
const DIRECT_LINE_BASE_URL = 'https://directline.botframework.com/v3/directline';

app.use(cors());
app.use(express.static('public')); // Serve your frontend files
app.use(express.json());

// Endpoint to create a Direct Line conversation
app.get('/api/directline/start-conversation', async (req, res) => {
  try {
    const response = await axios.post(
      `${DIRECT_LINE_BASE_URL}/conversations`,
      {},
      { headers: { Authorization: `Bearer ${DIRECT_LINE_SECRET}` } }
    );

    const { conversationId, token, expires_in } = response.data;
    res.json({ conversationId, token, expires_in });
  } catch (err) {
    console.error('Failed to create conversation:', err);
    res.status(500).json({ error: 'Could not initialize bot session' });
  }
});

app.listen(port, () => console.log(`Express server running on port ${port}`));
2. Frontend AJAX: Send User Messages to the Bot

Next, build your frontend to fetch the session details on load, then use AJAX to send user messages. Here's a sample HTML/JS setup using jQuery (adjust to your preferred AJAX library if needed):

<!DOCTYPE html>
<html>
<head>
  <title>Bot Chat</title>
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <style>
    #chat-messages { height: 300px; overflow-y: auto; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; }
    .user-msg { text-align: right; margin: 5px 0; color: #2c3e50; }
    .bot-msg { text-align: left; margin: 5px 0; color: #3498db; }
  </style>
</head>
<body>
  <div id="chat-messages"></div>
  <input type="text" id="user-input" placeholder="Type your message...">
  <button id="send-btn">Send</button>

  <script>
    let conversationId;
    let directLineToken;

    // Initialize session on page load
    $(document).ready(async () => {
      const sessionResponse = await $.get('/api/directline/start-conversation');
      conversationId = sessionResponse.conversationId;
      directLineToken = sessionResponse.token;
      console.log('Bot session initialized:', conversationId);

      // Start listening for bot messages
      startMessagePolling();
    });

    // Send user message via AJAX
    $('#send-btn').click(async () => {
      const messageText = $('#user-input').val().trim();
      if (!messageText) return;

      // Add user message to UI immediately
      $('#chat-messages').append(`<div class="user-msg">You: ${messageText}</div>`);
      $('#user-input').val('');
      scrollToBottom();

      try {
        await $.ajax({
          url: `https://directline.botframework.com/v3/directline/conversations/${conversationId}/activities`,
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${directLineToken}`,
            'Content-Type': 'application/json'
          },
          data: JSON.stringify({
            type: 'message',
            from: { id: 'unique-user-id' }, // Use a unique ID for each user
            text: messageText
          })
        });
      } catch (err) {
        console.error('Failed to send message:', err);
        $('#chat-messages').append('<div class="bot-msg">Error: Could not send message</div>');
        scrollToBottom();
      }
    });

    function scrollToBottom() {
      $('#chat-messages').scrollTop($('#chat-messages')[0].scrollHeight);
    }
  </script>
</body>
</html>
3. Receive Bot Messages (AJAX Polling or WebSocket)

Direct Line v3 supports two ways to get bot responses: long polling (AJAX-friendly) or WebSockets (more real-time).

Option 1: Long Polling (AJAX-Based)

Add this function to your frontend JS to poll for new messages at intervals:

let watermark = 0; // Tracks the last message we've received to avoid duplicates

function startMessagePolling() {
  setInterval(async () => {
    try {
      const response = await $.ajax({
        url: `https://directline.botframework.com/v3/directline/conversations/${conversationId}/activities?watermark=${watermark}`,
        method: 'GET',
        headers: { 'Authorization': `Bearer ${directLineToken}` }
      });

      if (response.activities.length > 0) {
        // Update watermark to fetch only new messages next time
        watermark = response.watermark;

        // Process each activity
        response.activities.forEach(activity => {
          // Only display messages from the bot (ignore system messages or user's own messages)
          if (activity.type === 'message' && activity.from.id !== 'unique-user-id') {
            $('#chat-messages').append(`<div class="bot-msg">Bot: ${activity.text}</div>`);
            scrollToBottom();
          }
        });
      }
    } catch (err) {
      console.error('Failed to fetch messages:', err);
    }
  }, 1000); // Poll every 1 second (adjust based on your real-time needs)
}

Option 2: WebSocket (More Efficient)

For near-instant updates, use WebSocket instead of polling. Replace the startMessagePolling function with this:

function connectWebSocket() {
  const socket = new WebSocket(`wss://directline.botframework.com/v3/directline/conversations/${conversationId}/stream?token=${directLineToken}`);

  socket.onopen = () => console.log('WebSocket connected to bot');

  socket.onmessage = (event) => {
    const envelope = JSON.parse(event.data);
    if (envelope.activity && envelope.activity.type === 'message' && envelope.activity.from.id !== 'unique-user-id') {
      $('#chat-messages').append(`<div class="bot-msg">Bot: ${envelope.activity.text}</div>`);
      scrollToBottom();
    }
  };

  socket.onerror = (err) => console.error('WebSocket error:', err);

  socket.onclose = () => {
    console.log('WebSocket disconnected. Reconnecting...');
    setTimeout(connectWebSocket, 5000); // Reconnect after 5 seconds if disconnected
  };
}
4. Key Best Practices
  • Security: Never expose your Direct Line secret in frontend code—your backend proxy is the correct approach here.
  • Token Expiry: Direct Line tokens expire after 30 minutes. Implement token refresh logic if your app needs long sessions (call the /conversations/{conversationId}/token/refresh endpoint from your backend).
  • Activity Schema: Ensure all outgoing messages follow the Direct Line Activity schema—required fields include type, from.id, and text for message activities.
  • Error Handling: Add retry logic for failed AJAX calls or WebSocket reconnections to make your chat more robust.

内容的提问来源于stack exchange,提问作者Sarthak Srivastava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:09:47