8

我正在使用 ASP.NET MVC 3 RTM,并且我有一个这样的视图模型:

public class TaskModel
{
  // Lot's of normal properties like int, string, datetime etc.
  public TimeOfDay TimeOfDay { get; set; }
}

TimeOfDay属性是我拥有的一个自定义结构,非常简单,所以我不在这里包括它。我制作了一个自定义模型绑定器来绑定这个结构。模型绑定器非常简单:

public class TimeOfDayModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        try
        {
            // Let the TimeOfDay struct take care of the conversion from string.
            return new TimeOfDay(result.AttemptedValue, result.Culture);
        }
        catch (ArgumentException)
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Value is invalid. Examples of valid values: 6:30, 16:00");
            return bindingContext.Model; // Also tried: return null, return value.AttemptedValue
        }
    }
}

我的自定义模型绑定器工作正常,但问题是无法转换或解析用户提供的值。发生这种情况时(当 TimeOfDay 构造函数抛出 时ArgumentException),我添加了一个模型错误,该错误正确显示在视图中,但用户键入的无法转换的值丢失了。用户输入值的文本框是空的,并且在 HTML 源代码中 value 属性设置为空字符串:“”。

编辑:我想知道它是否可能是我的编辑器模板做错了,所以我把它包括在这里:

@model Nullable<TimeOfDay>
@if (Model.HasValue)
{
    @Html.TextBox(string.Empty, Model.Value.ToString());
}
else
{
    @Html.TextBox(string.Empty);
}

如何确保发生绑定错误时值不会丢失,以便用户可以更正该值?

4

1 回答 1

17

啊哈!我终于找到了答案!这篇博文给出了答案。我缺少的是调用ModelState.SetModelValue()我的模型活页夹。所以代码会是这样的:

public class TimeOfDayModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        try
        {
            // Let the TimeOfDay struct take care of the conversion from string.
            return new TimeOfDay(result.AttemptedValue, result.Culture);
        }
        catch (ArgumentException)
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Value is invalid. Examples of valid values: 6:30, 16:00");
            // This line is what makes the difference:
            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, result);
            return bindingContext.Model;
        }
    }
}

我希望这可以帮助其他人摆脱我所经历的挫败感。

于 2011-04-04T09:12:33.587 回答