这是有效的,但是如何???
我有一个帖子的控制器动作:
[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 %>" />
答案 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));