asp.net MVC如何在回发时记住我的错误值?

时间:2010-04-05 20:40:10

标签: asp.net-mvc asp.net-mvc-2

这是有效的,但是如何???

我有一个帖子的控制器动作:

[AcceptVerbs(HttpVerbs.Post )]
public ActionResult Edit(Person person)
{
   bool isvalid = ModelState.IsValid;
   etc.

Person对象具有属性BirthDate,类型为DateTime。 当我在表单中输入一些无效数据时,说'blabla'显然不是有效的Datetime,它用正确的数据填充所有(其他)Person属性,并用新的空白DateTime填充BirthDate属性。 bool isvalid的值为'false'。 到目前为止一切都很好。

然后我这样做:

return View(p);

在视图中我有这个:

<%= Html.TextBox("BirthDate", String.Format("{0:g}", Model.BirthDate)) %>
<%= Html.ValidationMessage("BirthDate", "*") %>

Ant来了:我预测模型包含新的空白DateTime,因为我没有放入任何新数据。其次,当View显示某些内容时,它必须是DateTime,因为Model.BirthDate除了DateTime之外什么都不能容纳。 但令我惊讶的是,它显示了一个带有'blabla'值的文本框! (以及后面的红色*)

哪个是好的,因为用户可以看到他输入错误的内容,但是如何将该(blabla)字符串转移到DateTime字段中的View?

编辑: ModelState信息对我帮助很大。 我还注意到在MVC 2中,当你创建自己的模板时 Html.EditorFor() 你必须自己实现这种行为。 我创建了一个

DateTime.ascx 

在/ views / shared / EditorTemplates文件夹中,我必须检查此属性值是否存在模型状态错误,如果是,则显示无效数据而不是模型数据。

所以在视图中我用这个:

 <%= Html.LabelFor(model => model.DateOfBirth) %>

并在DateTime.ascx中我使用:

<%
bool invalidData = false;
string propertyName = ViewData.ModelMetadata.PropertyName;

ModelState ms = ViewData.ModelState[propertyName];
if (ms != null)
{
   invalidData = ms.Errors.Count > 0;
}
string valueToshow = invalidData ? ViewData.ModelState[propertyName].Value.AttemptedValue : String.Format("{0:g}", Model);
%>
<input class="text-box single-line" id="<%= propertyName %>" name="<%= propertyName %>" type="text" value="<%= valueToshow %>" />

3 个答案:

答案 0 :(得分:10)

ModelState为每个表单元素保存KeyValuePairs,其中键是字段名称,值是您在字段中放置的值。然后Html Helpers在ModelState中查找,如果没有显式指定值,它们将从ModelState中提取值。

答案 1 :(得分:4)

先前输入的值存储在ModelState中。当您在表单上出现错误时,帮助程序会从ModelState中提取值,而不是使用Model中的任何值或特定提供的值(如果您没有提供显式值,它将默认为模型如果没有错误就有一个值。)

答案 2 :(得分:1)

我在'postback'中有一些代码会删除无效的促销代码并将响应大写。即使您使用新值更新模型,也不会显示它,因为ModelState值优先(正如其他人已经回答的那样)。

  <%= Html.TextBox("PromoCode", Model.PromoCodes) %>

但如果您遇到这种情况并且您不希望旧值持续存在,则需要执行此操作:

ModelState.Remove("PromoCode"); 

或将新值明确设置为modelstate(可能是更好的方法):

ModelState.SetModelValue("PromoCode", 
      new ValueProviderResult(newValue, newValue, CultureInfo.CurrentCulture));