2011-04-03 110 views
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); 
} 

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

回答

17

啊哈!我终于找到了答案! This blog post给出了答案。我所缺少的是在我的模型活页夹中调用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; 
     } 
    } 
} 

我希望这节省了别人从我经历过的挫折时间。