在POST请求中使用viewmodel返回数据

时间:2011-05-08 14:26:21

标签: asp.net-mvc

我有一个像这样的视图模型:

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请求。

3 个答案:

答案 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)

李甘恩是个好消息。为了使答案更具体一点,在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 Helper Extensions,即Html.TextBoxFor(x=>x.Name)

在渲染Html时,Defaut模型绑定在ModelState中查找attemptValues。这里描述by Steve Sanderson.