使用后退按钮并重新提交表单时遇到问题,第二次提交时不会保留绑定到下拉列表的模型上的值。
在现实生活中,此代码是一个报告生成器 - 表单从用户收集参数,然后将其发布到显示数据的结果视图中。显然这是一个相当复杂的代码发布,但下面我有一些简单的代码表现出同样的错误:
我有一个这样的模型:
public class HomeModel
{
public string SomeText { get; set; }
public long SelectedItemId { get; set; }
public IEnumerable<SelectListItem> AvailableItems { get; set; }
}
提交模型实例的表单,如下所示:
@using(Html.BeginForm("Result", "Home", FormMethod.Get))
{
@Html.EditorFor(model => model.SomeText)
<br />
@Html.DropDownListFor(model => model.SelectedItemId, Model.AvailableItems)
<input type="submit" value="submit" />
}
一个显示细节的视图,如此
You Typed: @Html.DisplayFor(model => model.SomeText) <br />
You Selected: @Html.DisplayFor(model => model.SelectedItemId)
一个管理它的控制器:
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
HomeModel model = new HomeModel();
List<SelectListItem> items = new List<SelectListItem>();
for (int i = 0; i < 10; i++)
items.Add(new SelectListItem() { Value = i.ToString(), Text = i.ToString() });
model.AvailableItems = items;
return View(model);
}
public ActionResult Result(HomeModel model)
{
return View(model);
}
}
我填写表格,按提交。我被重定向到结果视图,一切都很顺利。
然后我在浏览器中按回来,我再次显示索引视图。
然后我再次提交表格,事情变得糟糕。尽管列表显示在浏览器中显示先前选择的值,但模型不会使用列表中的选定值进行重新填充。
正在更新字符串属性,在我显示此行为的真实代码中也是如此。
这只发生在IE中,我使用的是版本9.
答案 0 :(得分:1)
我找到了解决方案。
简短回答:请勿使用“Id”
为您的模型属性添加后缀当我第一次加载示例中的索引视图时,这就是呈现的内容:
<SELECT id=SelectedItemId name=SelectedItemId data-val-required="The field is required"...>
当我提交时,请按回然后检查来源,这是我得到的:
<select name="SelectedItem" id="SelectedItem">
请注意,元素的名称已更改,严重破坏了MVC的反序列化程序。
这可以在发布的网址中看到,当我第一次发布表单时,这是浏览器中显示的网址:
http://localhost:57175/Home/Result?SomeText=999&SelectedItemId=1
然后,当我再次按回并发布时,这就是显示的内容:
http://localhost:57175/Home/Result?SomeText=999&SelectedItem=1
我可以改变属性名称,但问题是它还会删除使用不显眼的验证所需的所有验证属性。任何人都可以告诉我如何保留这些吗?
答案 1 :(得分:1)
是的,现在这一切都正常。
这与我为验证插入脚本标记的位置有关。我是懒惰的,只是把它们放在视图的顶部,所以当整个页面被组装和渲染时,它们就在体内。
IE似乎对此有异常,当按下后退按钮时,脚本引用消失了,所有验证属性和我的属性名称中的“Id”也消失了。有点奇怪,但你去了
因此,故事的寓意是始终将脚本放在正确的位置。