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
相关产品推荐
相关产品推荐

