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

Razor Pages无刷新问答实现:保留历史对话的技术问询

无刷新聊天功能实现方案

问题背景

基于Razor Page的search.cshtml开发聊天功能,需求是发送问题到服务器、接收回复并保留所有历史对话。当前提交表单会刷新页面,历史对话丢失;尝试用Ajax但后端逻辑在SearchModel中,需要调整后端方法适配异步请求。


后端SearchModel修改

关键调整点:

  • 会话保存历史:Razor Page每次请求会创建新的Model实例,所以要把对话历史存在Session中
  • 提供异步接口:把OnPost改成返回JSON的异步方法,适配Ajax请求

修改后的代码:

using AzOpenAIChatDemo.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace AzOpenAIChatDemo.Pages
{
    public class SearchModel : PageModel
    {
        private readonly IAzOpenAIService _azOpenAIService;
        private readonly ILogger<SearchModel> _searchLogger;

        // 从Session读取对话历史,不存在则初始化
        public Dictionary<string, string> ConversationHistory
        {
            get
            {
                var json = HttpContext.Session.GetString("ConversationHistory");
                return string.IsNullOrEmpty(json) 
                    ? new Dictionary<string, string>() 
                    : JsonSerializer.Deserialize<Dictionary<string, string>>(json);
            }
            set
            {
                var json = JsonSerializer.Serialize(value);
                HttpContext.Session.SetString("ConversationHistory", json);
            }
        }

        public SearchModel(IAzOpenAIService azOpenAIService, ILogger<SearchModel> searchLogger)
        {
            _azOpenAIService = azOpenAIService;
            _searchLogger = searchLogger;
        }

        public void OnGet()
        {
            // 首次加载时确保会话中有历史记录
            if (ConversationHistory == null)
            {
                ConversationHistory = new Dictionary<string, string>();
            }
        }

        // 修改为异步方法,返回JsonResult
        public async Task<IActionResult> OnPostAsync(string chatInput)
        {
            var history = ConversationHistory;
            
            // 添加用户输入
            history.Add("userInput", chatInput);

            // 调用AI服务获取回复
            var response = await _azOpenAIService.GenerateTextAsync(chatInput);
            var content = response.Value.Choices[0].Message.Content;

            StringBuilder sb = new StringBuilder();
            sb.Append("\n\n\n");
            sb.Append(content);
            sb.Append("\n\n\n");

            // 添加AI回复
            history.Add("chatResponse", sb.ToString());

            // 保存回Session
            ConversationHistory = history;

            // 返回最新的对话对(用户输入+AI回复)
            return new JsonResult(new
            {
                UserMessage = chatInput,
                BotMessage = sb.ToString()
            });
        }
    }
}

注意:需要先在项目中启用Session,在Program.cs中添加:

// 添加Session服务
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(30);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

// 启用Session中间件(要放在app.UseRouting()之后,app.UseAuthorization()之前)
app.UseSession();

前端修改

1. Razor页面(search.cshtml)调整

去掉表单的method="post",确保聊天容器初始加载历史对话:

@page
@model SearchModel
@{
    ViewData["Title"] = "Search Document";
}

<div class="text-lg-start header">
    <h3>Search your documents</h3>
</div>

<div class="main-container">
    <div class="chat-container" id="chatContainer">
        @foreach (var message in Model.ConversationHistory)
        {
            <div class="@(message.Key == "userInput" ? "user-message" : "bot-message")">@message.Value</div>
        }
    </div>
    <form id="chat-form">
        <div class="textbox-container">
            <input type="text" id="chatInput" class="form-control" placeholder="Type your message...">
            <button type="submit" class="chat-button" title="Chat">
                <i class="fas fa-comment"></i>
            </button>
        </div>
    </form>
</div>

@section Scripts {
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="~/Chat.js"></script>
}

2. Chat.js实现Ajax提交

$(document).ready(function() {
    $('#chat-form').submit(function(e) {
        // 阻止表单默认提交(避免页面刷新)
        e.preventDefault();
        
        var chatInput = $('#chatInput').val().trim();
        if (!chatInput) return;

        // 先把用户消息添加到聊天框
        $('#chatContainer').append(`<div class="user-message">${chatInput}</div>`);
        // 清空输入框
        $('#chatInput').val('');
        // 滚动到底部
        $('#chatContainer').scrollTop($('#chatContainer')[0].scrollHeight);

        // Ajax提交请求
        $.ajax({
            url: '/Search', // Razor Page的路由
            type: 'POST',
            data: { chatInput: chatInput },
            success: function(response) {
                // 添加AI回复到聊天框
                $('#chatContainer').append(`<div class="bot-message">${response.BotMessage}</div>`);
                // 滚动到底部
                $('#chatContainer').scrollTop($('#chatContainer')[0].scrollHeight);
            },
            error: function(xhr, status, error) {
                console.error('请求出错:', error);
                $('#chatContainer').append(`<div class="bot-message">抱歉,处理请求时出错了</div>`);
            }
        });
    });
});

内容的提问来源于stack exchange,提问作者Waseem Omar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 01:05:18