ASP.NET Core 3.1中Razor Page Handler的Ajax POST请求返回400错误
问题分析与解决方案
核心问题:400错误根源是缺少CSRF防伪造令牌
Razor Pages默认强制启用防伪造验证,所有POST请求必须携带__RequestVerificationToken,否则会直接返回400错误。你的Ajax请求未包含该令牌,这是触发错误的主要原因。
分步解决
1. 给Ajax请求添加CSRF令牌
有两种实现方式:
方式一:通过请求头传递令牌
先在页面(比如_Layout.cshtml)中添加隐藏令牌字段:
@Html.AntiForgeryToken()
修改site.js中的Ajax请求,增加请求头携带令牌:
function updateStudent(id) { if (id != null && id != '') { // 获取页面中的防伪造令牌 const token = $('input[name="__RequestVerificationToken"]').val(); $.ajax({ type: "POST", url: "/Index?Handler=UpdateStudent", headers: { "RequestVerificationToken": token }, data: { id: id }, success: function (result) { }, error: function (response) { // 注意原代码里的failure是错误写法,jQuery Ajax用error console.log(response); } }); } }
方式二:将令牌包含在请求数据中
同样先确保页面有@Html.AntiForgeryToken(),然后修改data参数:
data: { id: id, __RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() },
2. 修正PageModel中的代码错误
你的OnGet方法是void类型,却尝试return _studentService.GetStudents();,这会直接编译报错。调整代码如下:
[Authorize] [AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")] public class IndexModel : PageModel { private readonly IStudentService _studentService; // 注入服务(确保你已经注册了IStudentService) public IndexModel(IStudentService studentService) { _studentService = studentService; } public void OnGet() { // 如果需要将学生列表存入Session供_Layout使用 var students = _studentService.GetStudents(); HttpContext.Session.SetObject("StudentList", students); } public IActionResult OnPostUpdateStudent(string id) { HttpContext.Session.SetString("SelectedStudent", id); return new JsonResult(new { success = true }); // 返回响应,方便前端处理结果 } }
3. 确保Session功能已正确配置
在Startup.cs中必须添加Session的配置,否则Session无法正常使用:
public void ConfigureServices(IServiceCollection services) { // 添加Session服务 services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); services.AddRazorPages(); // 其他服务注册代码... } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 其他中间件(如异常处理、静态文件)... // 必须在UseRouting之后、UseEndpoints之前添加UseSession app.UseSession(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); }
4. 修正JavaScript方法名大小写问题
HTML中调用的UpdateAll和JS中定义的updateAll大小写不一致,会导致函数未定义,统一为小写:
<select onchange="updateAll(this)" asp-items="studentList" class="form-control">
5. 确认Session扩展方法存在
你的代码中用到了GetObject扩展方法从Session读取对象,如果项目中没有实现,需要添加以下代码:
public static class SessionExtensions { public static void SetObject<T>(this ISession session, string key, T value) { session.SetString(key, JsonSerializer.Serialize(value)); } public static T GetObject<T>(this ISession session, string key) { var value = session.GetString(key); return value == null ? default : JsonSerializer.Deserialize<T>(value); } }
内容的提问来源于stack exchange,提问作者Yzak
相关产品推荐
相关产品推荐

