ASP.NET Core MVC提交表单时DateTime输入致ModelState无效求助
解决ASP.NET Core DateTime表单提交ModelState无效问题
问题概述
提交表单时,输入dd/MM/yyyy HH:mm tt格式的日期时间,模型绑定失败,导致ModelState.IsValid为false。
解决方案
1. 全局配置日期文化格式
ASP.NET Core默认使用服务器区域设置解析日期,若服务器文化为en-US,会默认期望MM/dd/yyyy格式,和输入的dd/MM/yyyy不匹配。可在Program.cs中全局设置自定义文化:
using System.Globalization; var builder = WebApplication.CreateBuilder(args); // 配置自定义日期文化 CultureInfo customCulture = new CultureInfo("en-US") { DateTimeFormat = { ShortDatePattern = "dd/MM/yyyy", LongTimePattern = "HH:mm tt", FullDateTimePattern = "dd/MM/yyyy HH:mm tt" } }; CultureInfo.DefaultThreadCurrentCulture = customCulture; CultureInfo.DefaultThreadCurrentUICulture = customCulture; // 添加Mvc服务 builder.Services.AddControllersWithViews(); var app = builder.Build(); // ... 其他中间件配置 app.Run();
2. 为模型绑定添加自定义日期转换器
如果全局文化配置不生效,可添加自定义模型绑定转换器,强制解析指定格式:
首先创建转换器类:
using Microsoft.AspNetCore.Mvc.ModelBinding; using System.Globalization; public class DateTimeModelBinder : IModelBinder { private readonly string _dateFormat = "dd/MM/yyyy HH:mm tt"; 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 (DateTime.TryParseExact(dateStr, _dateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date)) { bindingContext.Result = ModelBindingResult.Success(date); } else { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, $"日期格式必须为{_dateFormat}"); } return Task.CompletedTask; } }
然后在模型属性上应用该绑定器:
using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Mvc; namespace WebApplication1.Models { public class Student { [DataType(DataType.DateTime)] [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy HH:mm tt}", ApplyFormatInEditMode = true)] [ModelBinder(BinderType = typeof(DateTimeModelBinder))] public DateTime StartDate { get; set; } } }
3. 前端格式验证(可选)
在视图中添加前端验证,提前拦截格式错误的输入,避免提交到后端:
@{ ViewData["Title"] = "Home Page"; } @model Student <div class="text-center"> <form method="post" asp-action="Index"> @if (TempData["Error"]!= null) { <span>@TempData["Error"]</span> } <input type="text" class="form-control" value="14/01/2024 01:04 PM" asp-for="StartDate" asp-format="{0:dd/MM/yyyy HH:mm tt}"> <button type="submit" class="btn btn-success">Submit</button> </form> </div> <script> document.querySelector('form').addEventListener('submit', function(e) { const dateInput = document.querySelector('input[name="StartDate"]'); const regex = /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012])\/\d{4} (0[0-9]|1[0-9]|2[0-3]):[0-5][0-9] (AM|PM)$/; if (!regex.test(dateInput.value)) { e.preventDefault(); alert('请输入正确的日期时间格式:dd/MM/yyyy HH:mm tt'); } }); </script>
内容的提问来源于stack exchange,提问作者user2361451
相关产品推荐
相关产品推荐

