2011-05-08 186 views
1

视图模型返回数据我有像这样的视图模型:与POST请求

public class MyViewModel 
{ 
    public string Name { get; set; } 
    public List<Purchases> Purchases { get; set; } 
} 

此视图模型被发送到的视图,允许用户编辑名称属性。该采购属性仅用于创建一个下拉框为它:

<%: Html.DropDownListFor(t => t.Name, new SelectList(Model.Purchases, "Value", "Text")) %></p> 

这工作得很好。

然而,当我执行服务器端验证,然后返回查看,我得到一个对象空引用错误,因为购买属性现在设置为null。我猜这是因为当被提交表单,因为购买房地产没有被绑定到任何可编辑的控制,它没有被传递回用视图模型。

我怎样才能防止这种情况发生?我希望始终发回要发送的列表以及发布请求。

回答

1

您不需要发回列表。如果验证失败,那么只需从头开始重建视图模型。 MVC的主要卖点之一是它在无状态环境中的运行情况如何。 Web窗体使用ViewState做这种事情,我不认为你想要复制这种功能。

我想有此两个重载操作方法(这两个名称相同,但不同的方法签名)。一个具有[HttpGet()]属性,另一个具有[HttpPost()]。如果您的模型在POST上被发现无效,那么只需返回“GET”方法(注意:您需要传入重建视图所需的任何参数)。

当我说的回报,我的意思是:

return MyGetAction(); 

重定向到GET操作。

如果模型是有效的,那么你可以/应该执行RedirectToAction() GET操作(这意味着如果用户点击刷新按钮,它不会再次提交表单,这称为Post/Redirect/Get PRG)图案)

1

你不得不为每一个在除了选择列表中的列表中元素的一个隐藏的输入。话虽如此,我认为在服务器上缓存查询结果是处理重新填充列表的更好方法,如果您不想再次执行查询。如果服务器可以挂在它上面,那么通过线路发回数据是没有意义的。就我个人而言,除非它被证明是性能瓶颈,否则我甚至不会为高速缓存而烦恼。只需从数据库填充模型选择列表。

<% for (int i = 0; i < Model.Purchases.Length; ++i) { %> 
    <%: Html.Hidden(string.Format("Purchases[{0}]", i), Model.Purchases[i]) %> 
<% } %> 
1

李耿氏是即期。为了让答案更具体一些,在ModelState无效的情况下重新构建非标量值是非常常见的。这可以通过简单地返回Controller中的[HttpGet]版本来完成。但是,您可以简单地手动重新生成采购集合。随你便。

[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辅助扩展,即Html.TextBoxFor(x=>x.Name)

Defaut模型结合看在模型状态为呈现Html时的attemptValues。这里描述的是by Steve Sanderson.