ASP.NET Core 5.0 Razor Pages 为何Ajax提交JSON数组后模型绑定为空数组?
ASP.NET Core 5.0 Razor Pages 项目中,通过Ajax提交JSON数组时模型绑定失效,后端接收到的绑定结果为空数组。
前端提交代码
提交的JSON数组内容:
[ { "Order":1, "FileName":"bbed5ecf-4133-4681-b0f3-c11366ad3186.jpg" }, { "Order":2, "FileName":"737e60dc-0631-493d-947d-2f5948d7818c.jpg" }, { "Order":3, "FileName":"6c76f9d1-44bd-4b80-926e-2ce4307eb30b.jpg" } ]
Ajax调用逻辑:
function UpdateImageOrder() { $.ajax({ type: "POST", url: "/property/imagesorter", dataType: "json", headers: { "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val() }, data: JSON.stringify(newOrderDictionary), success: function (response) { } }); }
后端处理代码
Razor Page后置处理方法:
public async Task OnPostAsync(ImageOrder[] data) { } public class ImageOrder { public int Order { get; set; } public string FileName { get; set; } }
绑定失效由三处配置缺失共同导致,按以下步骤修改即可:
补充Ajax请求的Content-Type声明
jQuery Ajax默认Content-Type为application/x-www-form-urlencoded,后端不会将提交的JSON字符串按请求体JSON格式解析,需在Ajax配置中新增contentType: 'application/json',明确告知后端提交格式。修改后的Ajax核心配置片段:
$.ajax({ type: "POST", url: "/property/imagesorter", dataType: "json", contentType: 'application/json', // 新增配置 headers: { "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val() }, data: JSON.stringify(newOrderDictionary), success: function (response) { } });为后端参数添加FromBody绑定特性
Razor Pages默认模型绑定规则会从路由值、查询字符串、表单字段获取参数值,不会主动从请求体JSON内容绑定数组参数,需为参数添加[FromBody]特性,指定从请求体读取绑定。修改后的后端代码:
// 需引用 Microsoft.AspNetCore.Mvc 命名空间使用FromBody特性 public async Task OnPostAsync([FromBody] ImageOrder[] data) { // 可正常读取data数组内容执行后续逻辑 } public class ImageOrder { public int Order { get; set; } public string FileName { get; set; } }适配CSRF令牌的请求头读取规则
你将CSRF验证令牌放在了自定义请求头RequestVerificationToken中,ASP.NET Core默认只会从表单字段__RequestVerificationToken读取令牌,需在Startup.cs的ConfigureServices方法中添加配置,指定从请求头读取令牌:public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); // 新增 antiforgery 配置 services.AddAntiforgery(o => o.HeaderName = "RequestVerificationToken"); }
注:若不需要自定义请求头传CSRF令牌,也可将令牌直接嵌入提交的JSON对象中随请求体发送,无需修改Startup配置,但当前请求头的写法不会污染提交的业务数据,更适合纯JSON接口场景。
内容的提问来源于stack exchange,提问作者Greg

