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

Sla*_*uma 5 asp.net validation asp.net-mvc asp.net-mvc-3

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

[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; }
Run Code Online (Sandbox Code Playgroud)

HttpPost的控制器操作签名如下所示:

[HttpPost]
public ActionResult Edit(int id, MyViewModel viewModel)
{
    // MyViewModel contains the MyDate property ...
    // ...
    if (ModelState.IsValid)
    {
        // ...
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

在Razor视图中,我尝试了以下两种方式:

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

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

它不能按我的意愿工作.结果是:

  • 客户端验证与两个Html帮助程序一样正常工作
  • 对于两个帮助程序,服务器端验证总是失败,即使是通过正则表达式的有效日期(如"17.06.2011")也是如此.MyDate正确填充该属性,并将输入的日期viewModel传递给操作.所以似乎模型绑定工作正常.
  • DisplayFormat属性仅受到尊重,EditorFor但不受其尊重TextBoxFor.TextBoxFor显示"dd.mm.yyyy hh:mm:ss"

问题:

  1. 我可以RegularExpressionAttribute在不属于的房产上申请string吗?如果允许,如何DateTime在服务器端评估非字符串属性的reg ex ?是什么类似于MyDate.ToString()reg ex?(它会解释验证失败,因为ToString将返回一个包含时间部分的字符串,该字符串不会传递正则表达式.)

  2. DisplayFormat属性一般只能通过尊重EditorFor和从来没有TextBoxFor

  3. 我该如何进行日期验证呢?

Dar*_*rov 10

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

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

您可以使用<globalization>web.config中的元素来设置服务器端文化.您可以使用与客户端相同的文化来配置它:

<globalization culture="auto" uiCulture="auto"/>
Run Code Online (Sandbox Code Playgroud)

Hanselman 在ASP.NET MVC 上发表一篇关于全球化和本地化的博文.


Sla*_*uma 4

我现在已经扔掉了RegularExpression。它似乎不适合 type 的属性DateTime。然后我为 DateTime 和可为空的 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)]
[DateOnly]
public DateTime MyDate { get; set; }
Run Code Online (Sandbox Code Playgroud)

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