我有一个像这样的视图模型:
public class MyViewModel
{
public string Name { get; set; }
public List<Purchases> Purchases { get; set; }
}
此视图模型将发送到允许用户编辑name属性的视图。 Purchases属性仅用于为其创建下拉框:
<%: Html.DropDownListFor(t => t.Name, new SelectList(Model.Purchases, "Value", "Text")) %></p>
这很好用。
但是,当我执行服务器端验证然后返回View时,我收到一个对象null引用错误,因为Purchases属性现在设置为null。我猜这是因为提交表单时因为Purchases属性没有绑定到任何可编辑的控件,所以它不会与viewmodel一起传回。
如何防止这种情况发生?我想发回List以便随后发送回Post请求。
答案 0 :(得分:1)
除了选择列表之外,您还必须为列表中的每个元素创建隐藏输入。话虽如此,我认为如果您不想再次执行查询,那么在服务器上缓存查询结果是处理重新填充列表的更好方法。如果服务器可以直接挂起,那么将数据发送回电线是没有意义的。就个人而言,我甚至不会为缓存而烦恼,除非它被证明是性能瓶颈。只需从数据库填充模型选择列表。
<% for (int i = 0; i < Model.Purchases.Length; ++i) { %>
<%: Html.Hidden( string.Format( "Purchases[{0}]", i ), Model.Purchases[i] ) %>
<% } %>
答案 1 :(得分:1)
您无需发回列表。如果验证失败,则只需从头开始重建视图模型。 MVC的主要卖点之一是它在无状态环境中的运行情况。 Web窗体使用ViewState来做这种事情,我认为你不想复制这种功能。
我喜欢为此设置两个重载的Action方法(两个名称相同但方法签名不同)。一个具有[HttpGet()]
属性,另一个具有[HttpPost()]
。如果在POST上发现您的模型无效,则只需返回“GET”方法(注意:您需要传入重建视图所需的任何参数)。
当我说回来时,我的意思是:
return MyGetAction();
和不重定向到GET操作。
如果模型有效,那么您可以/应该对GET操作执行RedirectToAction()
(这意味着如果用户点击刷新按钮,它将不会再次提交表单,这称为发布/重定向/ Get(PRG)模式)
答案 2 :(得分:1)
[HttpGet]
public ActionResult MyView(string name)
{
//get entity and build up a view model
var entity = _myDb.GetEntity(name);
MyViewModel vm = AutoMapper.Map<Entity, MyViewModel>(entity);
return vm;
}
[HttpPost]
public ActionResult MyView(MyViewModel vm)
{
If(!ModelState.IsValid)
{
//here is one way of doing it
return MyView("");
//OR
vm.Purchases = GetSomePurchasesBro();
return View(vm);
}
//continue on persisting and doing the Post Redirect Get
}
P.S。 致电
return MyView("");
可以替换为
return MyView(vm.Name);
两者都会做同样的事情(前提是你正在使用Html Helper Extensions,即Html.TextBoxFor(x=>x.Name)
)
在渲染Html时,Defaut模型绑定在ModelState中查找attemptValues。这里描述by Steve Sanderson.