MVC 5 没有正确验证带有自定义 DateTime 注释的模型字段
MVC 5 does not validate properly a Model's field with custom DateTime annotation
在我的 ASP.NET MVC 5 项目中,我添加了一个 DataAnnotation 来格式化模型的 DateTime 字段,例如 "dd/mm/yyyy",但是当字段在编辑视图中由 @Html.EditorFor 呈现时这仍然被验证为像 "mm/dd/yyyy" 这样的日期(例如,如果我插入像“13/12/2019”这样的日期,我得到了一个错误,因为第 13 天被验证为一个月)。
这是从数据库生成的实体模型:
namespace MyProject
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public partial class Supplier
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Supplier()
{
this.Brands = new HashSet<Brand>();
}
public long Id { get; set; }
public string Name { get; set; }
public string Agent { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public Nullable<System.DateTime> NextOrderDate { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Brand> Brands { get; set; }
}
}
我使用解决方法 explained here 添加 DataAnnotations,这样当从数据库中重新生成实体时它们就不会被清除,所以我还添加了这个元数据 class:
namespace MyProject
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(SupplierMetadata))]
public partial class Supplier
{
// Note this class has nothing in it. It's just here to add the class-level attribute.
}
public class SupplierMetadata
{
[Required]
public string Name { get; set; }
[Required]
public string Agent { get; set; }
[Required]
public string Address { get; set; }
[Required]
public string Phone { get; set; }
[Required]
public string Email { get; set; }
[Display(Name = "Next Order")]
[DisplayFormat(DataFormatString = "{0:dd/mm/yyyy}")]
public Nullable<System.DateTime> NextOrderDate { get; set; }
}
这就是我的字段的呈现方式:
<div class="form-group">
@Html.LabelFor(model => model.NextOrderDate, htmlAttributes: new { @class = "col-form-label col-lg-2" })
<div class="col-lg-10">
@Html.EditorFor(model => model.NextOrderDate, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.NextOrderDate, "", new { @class = "text-danger" })
</div>
</div>
我也将此代码添加到 Global.asax.cs 但没有任何更改:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace MyProject
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
CultureInfo newCulture = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
newCulture.DateTimeFormat.ShortDatePattern = "dd/mm/yyyy";
newCulture.DateTimeFormat.DateSeparator = "/";
Thread.CurrentThread.CurrentCulture = newCulture;
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
我解决了这个问题,因为 jQuery 验证在解析日期时没有考虑文化。如果您关闭客户端验证,则日期在了解文化的服务器上解析得很好。解决方法是覆盖 jQuery 日期验证并包含一个额外的 jQuery 全球化插件。
我最终的解决方案是
安装 moment.js 使用:
安装包Moment.js
然后在视图中添加对日期格式解析器的修复:
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/Scripts/moment.js")
<script>
$(function () {
$.validator.methods.date = function (value, element) {
return this.optional(element) || moment(value, "DD/MM/YYYY", true).isValid();
}
});
</script>
}
在我的 ASP.NET MVC 5 项目中,我添加了一个 DataAnnotation 来格式化模型的 DateTime 字段,例如 "dd/mm/yyyy",但是当字段在编辑视图中由 @Html.EditorFor 呈现时这仍然被验证为像 "mm/dd/yyyy" 这样的日期(例如,如果我插入像“13/12/2019”这样的日期,我得到了一个错误,因为第 13 天被验证为一个月)。
这是从数据库生成的实体模型:
namespace MyProject
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public partial class Supplier
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Supplier()
{
this.Brands = new HashSet<Brand>();
}
public long Id { get; set; }
public string Name { get; set; }
public string Agent { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public Nullable<System.DateTime> NextOrderDate { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Brand> Brands { get; set; }
}
}
我使用解决方法 explained here 添加 DataAnnotations,这样当从数据库中重新生成实体时它们就不会被清除,所以我还添加了这个元数据 class:
namespace MyProject
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(SupplierMetadata))]
public partial class Supplier
{
// Note this class has nothing in it. It's just here to add the class-level attribute.
}
public class SupplierMetadata
{
[Required]
public string Name { get; set; }
[Required]
public string Agent { get; set; }
[Required]
public string Address { get; set; }
[Required]
public string Phone { get; set; }
[Required]
public string Email { get; set; }
[Display(Name = "Next Order")]
[DisplayFormat(DataFormatString = "{0:dd/mm/yyyy}")]
public Nullable<System.DateTime> NextOrderDate { get; set; }
}
这就是我的字段的呈现方式:
<div class="form-group">
@Html.LabelFor(model => model.NextOrderDate, htmlAttributes: new { @class = "col-form-label col-lg-2" })
<div class="col-lg-10">
@Html.EditorFor(model => model.NextOrderDate, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.NextOrderDate, "", new { @class = "text-danger" })
</div>
</div>
我也将此代码添加到 Global.asax.cs 但没有任何更改:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace MyProject
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
CultureInfo newCulture = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
newCulture.DateTimeFormat.ShortDatePattern = "dd/mm/yyyy";
newCulture.DateTimeFormat.DateSeparator = "/";
Thread.CurrentThread.CurrentCulture = newCulture;
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
我解决了这个问题,因为 jQuery 验证在解析日期时没有考虑文化。如果您关闭客户端验证,则日期在了解文化的服务器上解析得很好。解决方法是覆盖 jQuery 日期验证并包含一个额外的 jQuery 全球化插件。
我最终的解决方案是
安装 moment.js 使用:
安装包Moment.js
然后在视图中添加对日期格式解析器的修复:
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/Scripts/moment.js")
<script>
$(function () {
$.validator.methods.date = function (value, element) {
return this.optional(element) || moment(value, "DD/MM/YYYY", true).isValid();
}
});
</script>
}