发生TimeSpan模型绑定异常时显示验证错误

时间:2013-05-04 17:34:51

标签: asp.net asp.net-mvc validation asp.net-mvc-4 model-binding

在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.ValuesErrorMessage "The value \"a\" for \"My time\" is invalid."属性设置为消息(Exception),null属性为MyTimenull的绑定值为ErrorMessage

    "25:12"显示在页面的验证摘要中。

  • 如果我在输入元素中输入了无效时间(比如ModelError),则此属性的ErrorMessageException属性设置为空字符串,但InvalidOperationException 1}}属性设置为类型OverflowException的异常,内部异常类型为TimeSpan,告诉我MyTime无法分析,因为其中一个数字组件超出了有效范围。 null的绑定值为ErrorMessage

    同样,"The value \"25:12\" for \"My time\" is invalid."显示在页面的验证摘要中。但因为它是空的,所以它不是很有用。

理想情况下,对于第二种无效输入的情况,我更倾向于使用与第一种情况相同的错误消息,例如{{1}}。

我该如何解决这个问题?

修改

自定义验证属性显然在这里没有帮助,因为在模型绑定器检测到无效值时,上面的示例中没有调用无效输入。我尝试过这种方法但没有成功。

3 个答案:

答案 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