在ASP.NET MVC 4应用程序中,我有一个包含可空TimeSpan
属性的视图模型:
[DisplayName("My time")]
public TimeSpan? MyTime { get; set; }
它绑定到视图中的输入元素:
@Html.EditorFor(model => model.MyTime)
输入框在自定义编辑器模板TimeSpan.cshtml
的帮助下呈现:
@model Nullable<System.TimeSpan>
@Html.TextBox("", (Model.HasValue
? Model.Value.ToString(@"hh\:mm") : string.Empty),
new { @class = "text-box single-line hasTimepicker" data_timepicker = true })
现在,如果我输入以下两种无效时间并提交页面,我会得到以下模型绑定器的不同行为:
如果我输入一封信,请在导入"a"
集合时ModelError
对此属性的ModelState.Values
说ErrorMessage
"The value \"a\" for \"My time\" is invalid."
属性设置为消息(Exception
),null
属性为MyTime
。 null
的绑定值为ErrorMessage
。
此"25:12"
显示在页面的验证摘要中。
如果我在输入元素中输入了无效时间(比如ModelError
),则此属性的ErrorMessage
将Exception
属性设置为空字符串,但InvalidOperationException
1}}属性设置为类型OverflowException
的异常,内部异常类型为TimeSpan
,告诉我MyTime
无法分析,因为其中一个数字组件超出了有效范围。 null
的绑定值为ErrorMessage
。
同样,"The value \"25:12\" for \"My time\" is invalid."
显示在页面的验证摘要中。但因为它是空的,所以它不是很有用。
理想情况下,对于第二种无效输入的情况,我更倾向于使用与第一种情况相同的错误消息,例如{{1}}。
我该如何解决这个问题?
修改
自定义验证属性显然在这里没有帮助,因为在模型绑定器检测到无效值时,上面的示例中没有调用无效输入。我尝试过这种方法但没有成功。
答案 0 :(得分:2)
问题是错误发生在模型绑定中,而这正是您需要捕获并检查它的地方。
我有一个TimeSpan?
的Timespan模型活页夹和编辑器模板,它应该做你需要的up on Gist
答案 1 :(得分:1)
@ Chao的回答让我走上正确的轨道,使用自定义模型绑定器。
因为我希望尽可能保持默认模型绑定器的功能(输入格式的灵活性,本地化等)不变,并且只有在用户进入{{1}时才会为用户提供有用的错误消息或类似我创建了以下绑定器,它只检测默认模型绑定器是否已将"25:12"
(作为内部异常)添加到模型状态,如果是,则向状态添加错误消息:
OverflowException
在public class TimeSpanModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
object timeSpanValue = base.BindModel(controllerContext, bindingContext);
var modelState = bindingContext.ModelState[bindingContext.ModelName];
var hasOverflowException = modelState.Errors
.Any(e => e.Exception != null &&
e.Exception.InnerException is OverflowException);
if (hasOverflowException)
{
var rawValues = modelState.Value.RawValue as string[];
if (rawValues != null && rawValues.Length >= 1)
{
bindingContext.ModelState.AddModelError(
bindingContext.ModelName, string.Format(
"The value \"{0}\" for field \"{1}\" is invalid.",
rawValues[0],
bindingContext.ModelMetadata.GetDisplayName()));
}
}
return timeSpanValue;
}
}
/ global.asax
中添加到Application_Start()
集合中:
ModelBinders
答案 2 :(得分:0)
不确定这是否是您正在寻找的,但这个问题可能会有所帮助: Client side validation of a timespan on asp.net mvc 3