在ASP.NET MVC 3中以特定格式验证日期

在ASP.NET MVC 3中以特定格式验证日期,asp.net,asp.net-mvc,validation,asp.net-mvc-3,Asp.net,Asp.net Mvc,Validation,Asp.net Mvc 3,我的ViewModel中有一个类型为DateTime MyDate的属性。我希望确保用户仅以特定格式(dd.mm.yyyy)在文本框中输入日期部分,并尝试以下属性: [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)] [RegularExpression(@"^(([0-2]\d|[3][0-1])\.([0]\d|[1][0-2])\.[2][0]\d{2})$", ErrorMessage="

我的ViewModel中有一个类型为
DateTime MyDate
的属性。我希望确保用户仅以特定格式(dd.mm.yyyy)在文本框中输入日期部分,并尝试以下属性:

[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)]
[RegularExpression(@"^(([0-2]\d|[3][0-1])\.([0]\d|[1][0-2])\.[2][0]\d{2})$",
    ErrorMessage="Failed...")]
public DateTime MyDate { get; set; }
HttpPost的控制器操作签名如下所示:

[HttpPost]
public ActionResult Edit(int id, MyViewModel viewModel)
{
    // MyViewModel contains the MyDate property ...
    // ...
    if (ModelState.IsValid)
    {
        // ...
    }
    // ...
}
在Razor视图中,我尝试了以下两种方法:

  • @Html.TextBoxFor(model=>model.MyDate)

  • @Html.EditorFor(model=>model.MyDate)

  • 这不是我想要的。结果是:

    • 客户端验证在两个Html帮助程序中都能正常工作
    • 对于这两个帮助程序,服务器端验证总是失败,即使是通过正则表达式的有效日期,如“17.06.2011”。
      MyDate
      属性正确填写了
      viewModel
      中输入的日期,该日期将传递给操作。因此,模型绑定似乎起到了作用
    • DisplayFormat
      属性仅受
      EditorFor
      的约束,而不受
      TextBoxFor
      的约束<代码>文本框显示“dd.mm.yyyy hh:mm:ss”
    问题:

  • 我是否可以对不是
    字符串的属性应用
    RegularExpressionAttribute
    ?如果允许,如何对服务器端的非字符串属性(如
    DateTime
    )计算reg ex?与reg ex相比,类似于
    MyDate.ToString()
    ?(这将解释验证失败,因为ToString将返回一个字符串,其中包含不通过正则表达式的时间部分。)

  • DisplayFormat
    属性通常仅由
    EditorFor
    遵守,而从不由
    TextBoxFor
    遵守吗

  • 如何正确地进行日期验证


  • 不要使用正则表达式来验证日期,它们会被忽略

    文化差异可能是你问题的根源。客户端验证使用浏览器的区域性来验证日期。因此,例如,如果将其配置为
    en-US
    ,预期的格式将是
    MM/dd/yyyy
    。如果您的服务器配置为使用
    fr-fr
    ,则预期格式为
    dd/MM/yyyy

    可以使用web.config中的元素设置服务器端区域性。您可以将其配置为使用与客户端相同的区域性:

    <globalization culture="auto" uiCulture="auto"/>
    
    
    

    Hanselman在ASP.NET MVC中有一个关于全球化和本地化的概念。

    我现在扔掉了
    正则表达式。它似乎不适合类型为
    DateTime
    的属性。然后,我为DateTime和nullable DateTime创建了一个新的验证属性:

    [AttributeUsage(AttributeTargets.Property, Inherited = false,
        AllowMultiple = false)]
    public sealed class DateOnlyAttribute : ValidationAttribute
    {
        public DateOnlyAttribute() :
            base("\"{0}\" must be a date without time portion.")
        {
        }
    
        public override bool IsValid(object value)
        {
            if (value != null)
            {
                if (value.GetType() == typeof(DateTime))
                {
                    DateTime dateTime = (DateTime)value;
                    return dateTime.TimeOfDay == TimeSpan.Zero;
                }
                else if (value.GetType() == typeof(Nullable<DateTime>))
                {
                    DateTime? dateTime = (DateTime?)value;
                    return !dateTime.HasValue
                        || dateTime.Value.TimeOfDay == TimeSpan.Zero;
                }
            }
            return true;
        }
    
        public override string FormatErrorMessage(string name)
        {
            return string.Format(CultureInfo.CurrentCulture,
                ErrorMessageString, name);
        }
    }
    

    它不提供客户端验证。在服务器端,验证依赖于模型绑定(以确保输入的字符串可转换为
    DateTime
    )。如果用户输入的时间部分不是午夜,则
    DateOnly
    属性将生效,并且她将收到一条警告,提示只应输入日期。

    感谢链接,我已将其添加为书签,以备将来参考。但是:我认为我的问题与本地化无关。我不相信正则表达式会被忽略:客户端验证有效,服务器端验证也会对reg-ex做一些事情(正如ModelState所说,它会对这个reg-ex失败)。我在一台开发机器上进行测试(客户机和服务器=同一台机器),因此区域设置是相同的。但同时我也相信使用reg ex是错误的(尽管没有被忽略)。如何验证用户只输入日期而不输入时间部分?@Slauma,您在同一台机器上尝试此操作并不意味着浏览器和服务器的区域性设置没有差异。就时间部分而言,我会简单地告诉用户他需要输入日期的格式,在服务器上,如果我的应用程序不需要,我会简单地忽略时间部分。甚至可以提供jquery日期选择器来简化用户将日期输入到正确格式的过程。现在,作为对用户输入的一点额外帮助,我创建了一个
    DateOnly
    属性(请参见我自己的答案)。日期选择器对用户来说是一个更好的帮助!作为下一步之一,我将尝试这样做。
    [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)]
    [DateOnly]
    public DateTime MyDate { get; set; }