如何使用视图模型将选定列表的选定值发布到控制器?

时间:2011-02-09 21:38:13

标签: drop-down-menu asp.net-mvc-3 controller viewmodel

这个问题已经以各种形式提出,但没有一个答案似乎适合我的情况。我只是想在我的控制器中检索下拉列表的选定值。

这是我的代码:

ViewModel.cs

public class ViewModel
{
  public ViewModel() {}
  public ViewModel(Contact contact, IEnumerable<State> states)
    {
      this.Contact = contact;
      this.States = new SelectList(states, "Id", "Name", contact.StateId);
    }
  public Contact Contact {get;set;}
  public SelectList States {get;set;}
}

Controller.cs

[HttpPost]
public ActionResult Edit(ViewModel viewModel)
{
  _contactService.UpdateContact(viewModel.Contact);
  return RedirectToAction("Item", new {id = viewModel.Contact.Id});
}

View.cshtml

<button type="submit" onclick="javascript:document.update.submit()"><span>Update</span></button>//aesthic usage. 
@{using (Html.BeginForm("Edit", "Controller", FormMethod.Post, new { name = "update" }))
  {
   @Html.HiddenFor(m => m.Contact.Id)
   @Html.LabelFor(m => m.Contact.Name, "Name:")
   @Html.TextBoxFor(m => m.Contact.Name)

   <label for="state">State:</label>
   @Html.DropDownList("state", Model.States)
}
}

一切都按预期工作,除了下拉列表中的值没有在我发布的viewModel中传递给控制器​​。编辑页面和所有字段正确加载。下拉菜单正确绑定并正确显示其选定值。但是,当我发布时,我只获得一个传递给控制器​​的“Contact”对象。 “States”SelectList对象为null。

我尝试在我的viewModel contstructor中映射“StateId”属性,但这也不起作用。我做错了什么?

感谢。

2 个答案:

答案 0 :(得分:3)

我讨厌回答我自己的问题,但基于多个问题我加上无数的答案,我想我会总结一下我的发现。

首先感谢Filip,他的回答并没有完全解决我的问题,但它让我朝着正确的方向前进。 1

如果您要创建一个需要下拉列表的查看和编辑表单,以下是一些建议和问题。我将从我需要​​满足我需求的参数列表开始。

  1. 我认为强类型视图更可取。最小化魔术字符串。
  2. 视图模型应包含尽可能少的逻辑和无关元素。只有工作才能促进数据对象的收集。
  3. 下拉列表应显示所选值。
  4. 所选值应轻松映射回表单提交上的视图模型。
  5. 这可能听起来像一个明显且容易获得的列表,但对于MVC的新手,却不是。我将使用注释修改上面的代码。这就是我所做的。

    ViewModel.cs

    public class ViewModel
    {
      public ViewModel() {}
      public ViewModel(Contact contact, IList<State> states)
      {
    //no need to pass in a SelectList or IEnumerable, just what your service or repository spits out
        this.Contact = contact;
        this.States = states;
      }
      public Contact Contact {get;set;}
      public IList<State> States {get;set;}
    }
    

    Controller.cs //与上面没有什么不同

    public ActionResult Edit(int id)
    {
      var contact = _contactService.GetContactById(id);
      var states = _stateService.GetAllStates();
      return View(new ViewModel(contact, states));
    }
    
    public ActionResult Edit(ViewModel viewModel)
    {
      _contactService.UpdateContact(viewModel.Contact);
      return RedirectToAction("Edit", new {id = viewModel.Contact.Id });
    }
    

    观看//感谢Artirto post

    @{using (Html.BeginForm("Edit", "Controller", FormMethod.Post))
     {
      @Html.HiddenFor(m => m.Contact.Id)
      @Html.DropDownListFor(m => m.Contact.StateId, new SelectList(Model.States, "Id", "Name", @Model.Contact.StateId))
    <input type="submit" value="Save" />
    }
    }
    

答案 1 :(得分:2)

尝试使用@Html.DropDownListFor,如果“状态”是模型的一部分,您可以像这样使用它:

@Html.DropDownListFor(m => m.Contact.StateId, Model.States, "-- Please select a State --")其中m.State包含所选值。

另外,不要将IEnumerable与模型混淆,我会把它放在ViewBag / ViewData中。

它看起来像这样:

@Html.DropDownListFor(m => m.Contact.StateId, (IEnumerable<string>)ViewBag.States, "-- Please select a State --")

在您返回此视图的操作中,您需要初始化可枚举到ViewBag.States属性的State。