自定义格式日期的 MVC3 不显眼日期验证

Posted

技术标签:

【中文标题】自定义格式日期的 MVC3 不显眼日期验证【英文标题】:MVC3 Unobtrusive Date Validation on a custom formatted date 【发布时间】:2011-12-24 22:29:42 【问题描述】:

我有一个日期字段(我正在使用 jquery ui datepicker),格式是我格式化的,如下所示:

视图模型

[DisplayFormat(DataFormatString = "0:dd-MMM-yyyy", ApplyFormatInEditMode = true)]
public DateTime FooDate  get; set; 

查看

@html.EditorFor(m => m.FooDate)

这会以我想要的方式正确显示日期,例如09-Nov-2011

我遇到的问题是在我按下提交时发生的。它一直告诉我日期无效......它是有效的,你这个笨蛋!

有什么办法,我可以让 jquery/unobtrusive javascript 忽略此字段或允许此格式通过?到目前为止,我可以让表单工作的唯一方法是,如果我不格式化日期,或者使用 0:d 作为日期格式。

编辑: 我创建了一个完全独立的布局+视图+控制器+模型来测试这个愚蠢的东西。在 IE/Safari 中仍然不起作用。 我有来自 nuget 的最新 jquery.validate/unobtrusive 文件。

我的layout 是空的。它只加载以下文件:

"jquery-1.7.min.js"
"jquery-ui-1.8.16.min.js"
"jquery.validate.min.js"
"jquery.validate.unobtrusive.min.js"

我的 TestViewModel 很简单:

public class TestViewModel

    [Display(Name = "Test Date:")]
    [DisplayFormat(DataFormatString = "0:dd/MMM/yyyy", ApplyFormatInEditMode = true)]
    public DateTime? TestDate  get; set; 

我的 TestController 如下:

public class TestController : Controller

    public ActionResult Index()
    
        var m = new TestViewModel();
        m.TestDate = DateTime.Now;
        return View(m);
    

我的观点:

@using (Html.BeginForm())

    ViewContext.FormContext.ValidationSummaryId = "valSumId";
    @Html.ValidationSummary(false, "The following errors were found:");
    @Html.AntiForgeryToken()

    @Html.LabelFor(m => m.TestDate)
    <input type="date" id="TestDate" value="@Model.TestDate.Value.ToString("dd/MMM/yyyy")" />
    <input type="submit" />

没用。

你知道烦人的是什么吗?如果我将TestDate 更改为字符串,它仍然会失败。

【问题讨论】:

你声明日期选择器时是否设置了相同的日期格式? $('#date').datepicker( constrainInput: true, dateFormat: 'D, dd M yy'... 类似这样的 是的,我做到了。我在页面加载时从视图中加载了一个默认日期,但它仍然不喜欢它 就我而言,我在模型中格式化日期,我使用 string.format 直接在视图中执行此操作,并且验证通过。也许你可以试一试:) 【参考方案1】:

我认为您的格式字符串中的连字符(“-”)有问题:

[DisplayFormat(DataFormatString = "0:dd-MMM-yyyy", ApplyFormatInEditMode = true)]

默认情况下,不显眼的验证似乎不接受用于日期格式的连字符。

就我而言,我必须添加自定义客户端方法:

$.validator.methods.date = function (value, element) 
    var s = value;
    s = value.replace(/\-/g, '/');

    return this.optional(element) || !/Invalid|NaN/.test(new Date(s));
;

已实施here

【讨论】:

【参考方案2】:

所以看起来 jquery.validate.unobtrusiveinput type="date" 有问题。这一定是只出现在 IE 和 Safari 中的 bug。

当我删除不显眼的 js 文件时,它提交的表单很好。当我重新添加不显眼的 js 文件并将输入类型更改为文本时,它起作用了。

烦人的错误。需要修复。

【讨论】:

虽然我同意这个答案中表达的事实,但我不想删除不显眼的 js..there is this fix which helps my MSIE and Chrome browsers to be happier,涉及向验证器对象添加“日期”方法 This is another tweak to deal with an ios issue 还涉及对验证器日期方法的调整如果您在我之前评论中链接到的 sn-p 之后粘贴这个 sn-p,这将有效地将之前的逻辑与它的拥有 我有点仓促地发表了我的第一条评论。虽然它在一定程度上解决了您的问题,但它也试图让 jquery UI 日期选择器与日期字段配合得很好。那里的概念仍然适用......并且要清楚,我想我们正在处理的是覆盖(而不是“添加”)验证器对象的“日期”方法,该方法在不显眼的 js 文件中列出。跨度> 【参考方案3】:

这里真的有两件事:

    客户端验证 服务器端验证

两者都应该使用相同的格式才能工作。让我们首先处理服务器端验证。您可以为 DateTime 字段编写自定义模型绑定器,该绑定器将在绑定它们时使用指定的显示格式。这是example of such model binder。

接下来我们必须处理客户端验证。为此,您可以编写将附加到给定元素的自定义规则:

<script type="text/javascript">
    $.validator.addMethod(
        'myDateFormat', function (value, element) 
            // TODO: put your validation logic here that will parse the string
            // and validate it
            return false;
        ,
        'Please enter a date in the format dd-MMM-yyyy'
    );

    $(function () 
        // we attach the custom validation rule to the given input element
        $('#FooDate').rules('add', 'myDateFormat');
    );
</script>

你也可以使用adapters with a custom attribute。

【讨论】:

【参考方案4】:

就我而言,我使用文本字段作为日期,所以它不会导致 jquery 验证出现问题:

 <div class="editor-field">
    @Html.TextBox("ExpiryDate", String.Format("0:ddd, dd MMM yyyy", DateTime.Now), new  id = "expirydate" )
    @Html.ValidationMessageFor(model => model.ExpiryDate)
</div>

那么您为什么不尝试像这样格式化您的日期,而不是使用输入 type=date?

希望得到帮助:)

【讨论】:

【参考方案5】:

实际上这不是浏览器中的错误,客户端验证问题可能是由于 jquery.validate.unobtrusive.min.js 中的 MVC 错误(即使在 MVC 5 中)不接受任何方式的日期/日期时间格式。不幸的是,您必须手动解决它。

我的最终解决方案:

之前必须包含:

@Scripts.Render("~/Scripts/jquery-3.1.1.js")
@Scripts.Render("~/Scripts/jquery.validate.min.js")
@Scripts.Render("~/Scripts/jquery.validate.unobtrusive.min.js")
@Scripts.Render("~/Scripts/moment.js")

您可以使用以下方式安装 moment.js:

Install-Package Moment.js

然后你终于可以为日期格式解析器添加修复:

$(function () 
    $.validator.methods.date = function (value, element) 
        return this.optional(element) || moment(value, "DD.MM.YYYY", true).isValid();
    
);

【讨论】:

【参考方案6】:

正如 lukyer 所发布的,可能存在与 jquery.validate*.min.js 文件相关的问题,尤其是如果您已将自己的验证添加到这些文件中。当最终发布系统无法在 IE 中验证日期(Chrome 正常工作)时,我发现对我有用的简单答案是简单地完全删除预先打包的缩小验证文件,让野兽从“主”处理它自己的缩小"文件。唯一遗憾的是我之前没有将 lukyer 的回复与解决方案联系起来......

(我可能会将此作为评论发布,但显然我还没有获得足够的代表:必须更加努力!)

【讨论】:

【参考方案7】:

您是否尝试过简单地将类型更改为:

@Html.TextBoxFor(model => model.startDate, new  @class = "date" )

我在使用 EditorFor... 时遇到了同样的问题,所以我将其更改为这个,然后将我的 jquery datepicker 应用于添加到文本框的“日期”类。

【讨论】:

【参考方案8】:

如果其他人以后遇到问题,只是想对这一行发表一点评论:

<input type="date" id="TestDate" value="@Model.TestDate.Value.ToString("dd/MMM/yyyy")" />

在某些情况下(至少我之前的情况),这会转化为这种格式:“01.01.2012”,因为在某些文化中,您不能指定这样的斜杠来实际将其格式化,它只会变成这样它们变成了点,所以我不得不写:

@Model.TestDate.Value.ToString("dd\/MMM\/yyyy");

这给了我“01/01/2012”。

【讨论】:

【参考方案9】:

这个帖子很老了。刚到这里就有类似的问题。在另一个线程中,我读到所有这些 *.js 库以某种方式在验证中涉及的版本不兼容可能存在问题。 也许以下链接可以帮助其他读者在这里登陆: https://***.com/a/16551039

希望对你有帮助

【讨论】:

【参考方案10】:

我遇到了同样的问题,这让我很生气!基本上,mvc 验证将始终呈现 DateTime 对象以要求文本框上的值。为什么?因为它直接与DateTime 对象相关联。如果您使用 ? 声明您的 ViewModel符号,您将使其可为空。这样就不会打扰您要求验证:

public class MyViewModel

    DateTime? StartDate  get; set; 

希望对你有帮助

【讨论】:

以上是关于自定义格式日期的 MVC3 不显眼日期验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 jQuery datepicker 自定义日期格式验证(无法摆脱美国日期验证)

使用 jQuery 验证插件自定义日期格式

Js 自定义日期格式的正则表达式验证

ASP .Net MVC 3:自定义不显眼的验证

自定义不显眼的验证方法未按照文档触发

自定义表单验证注释不起作用