.NET 7中Ajax传递null数组到控制器被解析为空数组的原因
.NET 7 MVC中jQuery Ajax传递null字符串数组绑定问题解决方法
问题原因
ASP.NET MVC默认模型绑定器对未提交的数组类型参数,会自动初始化为长度为0的空数组,而非null。这是绑定器的默认行为:对于引用类型数组,即使没有收到对应请求参数,也会实例化空数组而非保留null。
解决方案
方法1:使用可空数组+配置模型绑定空值处理
将控制器参数改为可空数组,并配置模型绑定器允许未提交参数返回null:
控制器代码:
[HttpPost] public ActionResult Process(int employeeId, string[]? yearsWorked, string reason, string authorizer)
Program.cs/Startup.cs配置:
builder.Services.AddControllersWithViews() .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; options.JsonSerializerOptions.PropertyNamingPolicy = null; options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; }) .AddMvcOptions(options => { // 配置未提交参数时返回null options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(_ => "值不能为空"); options.NullValueHandling = NullValueHandling.Ignore; });
方法2:显式传递null并使用JSON格式请求
修改Ajax代码,显式设置yearsWorked: null,同时确保请求以JSON格式发送(默认jQuery会将对象转为表单格式,无法正确传递null):
Ajax代码:
$('#' + freezeBtnId).on('click', function () { var url = '/Employee/Process'; var data = { employeeId: $('#hdnId').val(), yearsWorked: null, // 显式传递null reason: $('#txtReason').val(), authorizer: $('#txtAuthorizer').val() }; $.ajax({ url: url, type: 'POST', cache: false, async: true, contentType: "application/json", // 指定JSON内容类型 data: JSON.stringify(data), // 序列化为JSON字符串 success: function (data) { alert('success'); } }); });
此方法下,控制器参数可保持string[] yearsWorked,JSON格式的null会被模型绑定器正确解析为null数组。
方法3:自定义模型绑定器
创建自定义绑定器,处理数组类型参数,当请求中无该参数时返回null:
自定义绑定器代码:
public class NullableArrayModelBinder<T> : IModelBinder where T : class { public Task BindModelAsync(ModelBindingContext bindingContext) { var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueProviderResult == ValueProviderResult.None) { // 无对应参数时返回null bindingContext.Result = ModelBindingResult.Success(null); return Task.CompletedTask; } // 有参数时使用默认绑定逻辑 var defaultBinder = new SimpleTypeModelBinder(typeof(T[])); return defaultBinder.BindModelAsync(bindingContext); } }
控制器参数应用绑定器:
[HttpPost] public ActionResult Process(int employeeId, [ModelBinder(typeof(NullableArrayModelBinder<string>))] string[] yearsWorked, string reason, string authorizer)
也可以全局注册该绑定器,避免每个参数手动标注:
builder.Services.AddControllersWithViews() .AddMvcOptions(options => { options.ModelBinderProviders.Insert(0, new BinderTypeModelBinderProvider(typeof(NullableArrayModelBinder<>))); });
内容的提问来源于stack exchange,提问作者Mikey
相关产品推荐
相关产品推荐

