【发布时间】:2017-08-24 05:20:33
【问题描述】:
在创建具有不显眼验证的仅时间输入字段时遇到一些问题,映射到不可为空的 DateTime 字段。
我正在使用数据库优先的方法。该数据库具有用于存储日期和时间的日期时间字段。我的意思是一些日期时间有真实的日期数据和 00:00:00 的时间,而其他的有无意义的实时日期数据。我知道这是由于 EF5 和 C# 数据类型的限制。现在正在使用 EF6,但不是特别打算更改数据库。
这是视图模型
[UIHint("Date")]
public DateTime MatchDate { get; set; }
[UIHint("Time")]
public DateTime StartTime { get; set; }
仅日期字段 MatchDate 正在工作。它使用 EditorFor 模板,Date.cshtml(如下)。它允许文本输入,正确附加一个 jQuery 日期选择器并正确验证服务器端和客户端,并且不显眼。
@model DateTime
@if (Model == DateTime.MinValue)
{
@Html.TextBox("", "", new { @class = "datepicker" })
}
else
{
@Html.TextBox("", String.Format("{0:d/M/yyyy}", Model), new { @class = "datepicker" })
}
所以我为Time.cshtml创建了一个新的EditorFor模板
@model DateTime
@if (Model == DateTime.MinValue)
{
@Html.TextBox("", "", new { @class = "timepicker" })
}
else
{
@Html.TextBox("", String.Format("{0:h\\:mm tt}", Model), new { @class = "timepicker" })
}
此时,Html 输入元素获得了一个不需要的data-val-date 属性,导致不显眼的日期 验证。我发现通过添加[DataType(DataType.Time)],不再添加data-val-date。虽然这是一件好事,但如果这正是(并且唯一)数据类型属性应该做的事情,我不是。所以这是问题的第一部分。
接下来,我为 12 小时时间格式创建了自定义验证规则(服务器端和客户端)。
注释:
public class TimeTwelveAttribute : ValidationAttribute, IClientValidatable
{
private const string _ErrorMessage = "Invalid time format. Please use h:mm am/pm (TimeAttribute)";
public TimeTwelveAttribute()
{
this.ErrorMessage = _ErrorMessage;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = _ErrorMessage,
ValidationType = "timetwelve"
};
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
DateTime time;
if (value == null || !DateTime.TryParse(value.ToString(), out time))
{
return new ValidationResult(_ErrorMessage);
}
return ValidationResult.Success;
}
}
javascript
$.validator.unobtrusive.adapters.addSingleVal("timetwelve");
$.validator.addMethod(
"timetwelve",
function (value, element) {
return this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(value);
},
"Invalid time format. Please use h:mm am/pm"
);
但是,在 StartTime 中添加[TimeTwelve] 数据注解没有任何作用:
- 正在进行服务器端验证,但它创建了一条我无法覆盖的不同错误消息:“值 'asdf' 对于开始时间无效。”
- 如果我在时间字段中输入“asdf”,则不会弹出客户端验证消息。
我认为这是由于回发值被映射到 C# DateTimes 造成的。无论采用何种机制,它都具有更高的优先级并覆盖所有其他验证。作为练习,我将 StartTime 重写为一个字符串(并更新了模板等),果然[TimeTwelve] 在客户端和服务器端都能正常工作。我觉得这是 stackoverflow 上的任何相关问题都没有涉及到的方面。
所以我的问题的第二部分,鉴于我真的更喜欢在我的视图模型中使用 DateTimes,我怎样才能让验证工作?
This 是我能找到的最接近的问题,但来自 2013 年。
【问题讨论】:
-
如果您只处理时间,那么您的视图模型中的属性应该是
TimeSpan而不是DateTime -
DateTime小时整数值限制为 23。要使用两个时间范围之间的差异,请改用TimeSpan(它包括天、小时、分钟和秒)。 -
@StephenMuecke 谢谢。您将如何使用 TimeSpan 处理子午线指标?为什么 TimeSpan 比字符串更好?
-
你的意思比
DateTime更好吗?但是再次阅读问题并注意到您不想更改数据库(尽管如果您只需要时间,它确实应该存储为TIME) -
是的,如果您要提交“asdf”,
DefaultModelBinder无法将其转换为DateTime,这会添加 值“asdf”对于开始时间无效。ModelState出错并且没有进行进一步的验证(因为没有意义)。
标签: c# asp.net-mvc datetime asp.net-mvc-5