ASP.NET Core 9中Safari浏览器下数据注解日期验证失败问题
解决方案
1. 前端调整:让flatpickr完全接管输入,避免原生日期控件干扰
将TextBoxFor中的type = "date"改为type = "text",防止Safari的原生日期输入行为篡改flatpickr的输出格式:
<div class="col-md-4"> @Html.LabelWithMandateFor(m => m.WOHeader.EXP_DEL_DATE) @Html.TextBoxFor(m => m.WOHeader.EXP_DEL_DATE, "{0:dd-MM-yyyy}", new { @class = "form-control flatpickr flatpickr-input " + woInfo, type = "text", data_provider = "flatpickr" }).DisableIf(() => !Model.FLD_STATUS.REQ_DEL_DATE_OK) <span class="invalid-feedback" asp-validation-for="WOHeader.EXP_DEL_DATE"></span> </div>
同时在页面JS中明确配置flatpickr的输出格式为dd-MM-yyyy:
$('.flatpickr').flatpickr({ dateFormat: "dd-MM-yyyy", // 其他所需配置项 });
2. 确保RequestLocalization中间件正确启用
检查program.cs中是否添加了请求本地化中间件(需放在路由中间件之前),否则自定义文化配置不会生效:
// 配置完RequestLocalizationOptions后添加 app.UseRequestLocalization(); app.UseRouting(); // 其他中间件逻辑
3. 全局/局部配置DateOnly的强制解析规则
如果前端调整后仍存在解析问题,可通过自定义模型绑定器强制按dd-MM-yyyy格式解析日期:
全局绑定器(适用于所有DateOnly字段)
创建自定义绑定器类:
public class DateOnlyModelBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) throw new ArgumentNullException(nameof(bindingContext)); var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueProviderResult == ValueProviderResult.None) return Task.CompletedTask; bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); var dateStr = valueProviderResult.FirstValue; if (string.IsNullOrEmpty(dateStr)) return Task.CompletedTask; if (DateOnly.TryParseExact(dateStr, "dd-MM-yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out var date)) { bindingContext.Result = ModelBindingResult.Success(date); } else { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, "无效的日期格式,请使用dd-MM-yyyy"); } return Task.CompletedTask; } }
在program.cs中注册全局绑定器:
builder.Services.AddControllersWithViews(options => { options.ModelBinderProviders.Insert(0, new BinderTypeModelBinderProvider(typeof(DateOnly), new DateOnlyModelBinder())); });
局部特性(仅针对当前字段)
直接在EXP_DEL_DATE字段上添加绑定转换器特性:
[BindProperty] [Required(ErrorMessageResourceType = typeof(MsgsResource), ErrorMessageResourceName = MandatoryFld)] [JsonPropertyName("expDelDate")] [Display(Name = nameof(CommonResource.ExpDelDate), ResourceType = typeof(CommonResource))] [DataType(DataType.Date)] [DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)] [BindConverter(typeof(DateOnlyConverter), "dd-MM-yyyy")] // 添加此行 public DateOnly EXP_DEL_DATE { get; set; }
对应的转换器类:
public class DateOnlyConverter : IModelBinder { private readonly string _format; public DateOnlyConverter(string format) { _format = format; } public Task BindModelAsync(ModelBindingContext bindingContext) { var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueProviderResult == ValueProviderResult.None) return Task.CompletedTask; var dateStr = valueProviderResult.FirstValue; if (string.IsNullOrEmpty(dateStr)) return Task.CompletedTask; if (DateOnly.TryParseExact(dateStr, _format, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date)) { bindingContext.Result = ModelBindingResult.Success(date); } else { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, $"无效的日期格式,请使用{_format}"); } return Task.CompletedTask; } }
4. 验证Ajax提交的数据格式
提交表单前可添加简单的格式校验,确保日期值未被篡改:
$('form').submit(function(e) { e.preventDefault(); var expDelDate = $('#WOHeader_EXP_DEL_DATE').val(); var dateRegex = /^\d{2}-\d{2}-\d{4}$/; if (!dateRegex.test(expDelDate)) { alert('请输入正确的日期格式(dd-MM-yyyy)'); return; } // 执行Ajax提交逻辑 $.ajax({ url: $(this).attr('action'), method: $(this).attr('method'), data: $(this).serialize(), success: function(response) { // 处理响应 } }); });
内容的提问来源于stack exchange,提问作者Ryan Ong
相关产品推荐
相关产品推荐

