如果ModelState.IsValid为false,则重新填充某些属性值

时间:2011-04-10 09:51:34

标签: c# asp.net-mvc asp.net-mvc-2 asp.net-mvc-3 viewmodel

我有以下操作方法(部分代码):

[HttpPost]
public ActionResult Create(EditGrantApplicationViewModel editGrantApplicationViewModel)
{
   if (!ModelState.IsValid)
   {
      return View("Create", editGrantApplicationViewModel);
   }

   return View("Index");
}

EditGrantApplicationViewModel看起来像这样(部分代码):

public class EditGrantApplicationViewModel
{
   public IEnumerable<Title> Titles { get; set; }
   public int TitleId { get; set; }
   public IEnumerable<Bank> Banks { get; set; }
   public int BankId { get; set; }
   public IEnumerable<AccountType> AccountTypes { get; set; }
   public int AccountTypeId { get; set; }
}

首次请求此Create视图时,我会在我的服务层中填充Titles,只返回EditGrantApplicationViewModel这样的实例:

public ActionResult Create()
{
   EditGrantApplicationViewModel editGrantApplicationViewModel = grantApplicationService.CreateEditGrantApplicationViewModel();

   return View(editGrantApplicationViewModel);
}

我服务层中的CreateEditGrantApplicationViewModel

public EditGrantApplicationViewModel CreateEditGrantApplicationViewModel()
{
   EditGrantApplicationViewModel editGrantApplicationViewModel = new EditGrantApplicationViewModel
   {
      Titles = titleRepository
         .GetAll()
         .Where(x => x.Active)
         .OrderBy(x => x.Name)
   };

   return editGrantApplicationViewModel;
}

当我点击提交按钮时,它将进入后期操作Create方法。它会收到类型为editGrantApplicationViewModel的{​​{1}}参数。为什么Titles属性设置为null?我以为它会保留它的值?

现在假设有错误,EditGrantApplicationViewModel为false。所以这意味着我将不得不重新填充ModelState.IsValid属性。鉴于已在Titles中的表单中设置的属性值,我现在如何填充Titles属性?我假设我需要在我的服务层中使用另一种方法来填充它?这样做的最佳方式是什么?

任何源代码都将受到赞赏。

更新2011-04-11

在我看来,我有3个下拉菜单。标题,银行和帐户类型。这就是为什么我的视图模型中有3个列表。我有一个服务类,每个服务类来处理插入,更新和获取项目。例如,在我的银行服务类中,我将使用与银行相关的Insert,Update,GetAll,GetById等方法。我会在标题和帐户类型服务中有类似的内容。

这就是我目前在控制器类中使用它的方式:

editGrantApplicationViewModel

我们说了一会儿,你说最好为控制器提供一项服务。在我的情况下,我需要从3个不同的数据库表中填充3个列表。你能否提供一些代码来说明你将如何做到这一点。如果需要更多细节,请告诉我。

2 个答案:

答案 0 :(得分:2)

服务层不应返回视图模型,它应该与模型一起使用。因此,您的服务层会返回这些标题:

public IEnumerable<Title> GetTitles()
{
    return titleRepository
        .GetAll()
        .Where(x => x.Active)
        .OrderBy(x => x.Name)
    };
}

然后将实例化视图模型的责任留给控制器:

public ActionResult Create()
{
    var model = new EditGrantApplicationViewModel 
    {
        Titles = grantApplicationService.GetTitles()
    };
    return View(model);
}

[HttpPost]
public ActionResult Create(EditGrantApplicationViewModel model)
{
    if (!ModelState.IsValid)
    {
        // Reload the Titles as we are redisplaying the same view
        // and they were not part of the view model that was submitted
        model.Titles = grantApplicationService.GetTitles();
        return View("Create", model);
    }
    return View("Index");
}

答案 1 :(得分:0)

因为mvc是无状态的(因为你可以使用TempData和session维护某些状态)。在初始请求和显示之后,titles属性基本上丢失了。

要重新构建Titles,您需要在表单上以某种方式显示这些值,以便ModelBinder可以为您的EditGrantApplicationViewModel

补充水分

你很可能需要做这样的事情:

<% foreach(Title title in Model.Titles { %>
  <%: Html.HIddenFor(m => title) %>
<% } %>

请注意我的语法可能有点偏,因为我的机器上没有visual studio。

此外,我不确定ModelBinder如何处理您的IEnumberable<T>,您可能需要将其更改为List<T>,以便ModelBinder可以正确构建类型。

有关如何绑定到Titles列表的其他信息。

  1. Post from Phil Haack about Model Binding To A List
  2. A slightly smiler question about mvc and IEnumerable<T>