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

时间:2011-06-17 15:40:00

标签: asp.net asp.net-mvc validation asp.net-mvc-3

我的ViewModel中有一个DateTime MyDate类型的属性。我想确保用户只在特定格式(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; }

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

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

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

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

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

  3. 它无法正常工作。结果是:

    • 客户端验证与两个Html帮助程序一样正常工作
    • 对于两个帮助程序,服务器端验证始终失败,即使是有效日期(如“17.06.2011”)也会传递正则表达式。 MyDate属性已正确填充,并在viewModel中输入了传递给操作的日期。所以模型绑定似乎正在发挥作用。
    • DisplayFormat属性仅由EditorFor尊重,但不受TextBoxFor尊重。 TextBoxFor显示“dd.mm.yyyy hh:mm:ss”

    问题:

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

    2. MyDate.ToString()属性通常仅由DisplayFormat尊重,而不是EditorFor吗?

    3. 如何进行日期验证?

2 个答案:

答案 0 :(得分:10)

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

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

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

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

Hanselman在ASP.NET MVC中有关于全球化和本地化的nice blog post

答案 1 :(得分:4)

我现在扔掉了RegularExpression。它似乎不适合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);
    }
}

用法:

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

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