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

C# 如果ModelState.IsValid为false,则重新填充某些属性值,c#,asp.net-mvc,asp.net-mvc-2,asp.net-mvc-3,viewmodel,C#,Asp.net Mvc,Asp.net Mvc 2,Asp.net Mvc 3,Viewmodel,我有以下操作方法(部分代码): EditGrantApplicationViewModel如下所示(部分代码): 我的服务层中的CreateEditGrantApplicationViewModel: public EditGrantApplicationViewModel CreateEditGrantApplicationViewModel() { EditGrantApplicationViewModel editGrantApplicationViewModel = new Edi

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

EditGrantApplicationViewModel
如下所示(部分代码):

我的服务层中的
CreateEditGrantApplicationViewModel

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

   return editGrantApplicationViewModel;
}
当我单击submit按钮时,它将进入PostAction
Create
方法。它接收类型为
editGrantApplicationViewModel
editGrantApplicationViewModel
参数。为什么Titles属性设置为null?我以为它会保留它的价值观

现在假设有一个错误,
ModelState.IsValid
为false。这意味着我必须重新填充
Titles
属性。给定已在
editGrantApplicationViewModel
中的表单中设置的属性值,我现在如何填充Titles属性?我假设在我的服务层中需要另一个方法来填充它?最好的方法是什么

任何源代码将不胜感激

更新2011-04-11

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

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

private IGrantApplicationService grantApplicationService;
private ITitleService titleService;
private IBankService bankService;
private IAccountTypeService accountTypeService;

public GrantApplicationController(IGrantApplicationService grantApplicationService, ITitleService titleService, IBankService bankService, IAccountTypeService accountTypeService)
{
   this.grantApplicationService = grantApplicationService;
   this.titleService = titleService;
   this.bankService = bankService;
   this.accountTypeService = accountTypeService;
}

public ActionResult Create()
{
   EditGrantApplicationViewModel editGrantApplicationViewModel = new EditGrantApplicationViewModel
   {
      // Populate the dropdown lists
      Titles = titleService
         .GetAll()
         .Where(x => x.Active)
         .OrderBy(x => x.Name),
      Banks = bankService
         .GetAll()
         .Where(x => x.Active)
         .OrderBy(x => x.Name),
      AccountTypes = accountTypeService
         .GetAll()
         .Where(x => x.Active)
         .OrderBy(x => x.Name)
   };

   return View(editGrantApplicationViewModel);
}
我们之前谈过,您说过最好为控制器提供一个服务。在我的例子中,我需要从3个不同的数据库表填充3个列表。请你提供一些代码,说明你是如何做到这一点的。如果需要更多详细信息,请告诉我。

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

要重新生成
标题
,您需要以某种方式在表单上显示这些值,以便
ModelBinder
可以重新水化您的
EditGrantApplicationViewModel

您很可能需要执行以下操作:

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

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

标题)%%>
注意我的语法可能有点不正确,因为我的机器上没有visual studio

此外,我不确定ModelBinder将如何处理您的
IEnumberable
,您可能必须将其更改为
List
,以便ModelBinder能够正确地构建类型

有关如何绑定到
标题
列表的其他信息


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

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

    在这个控制器的构造函数中,我通过构造函数注入传递一个IGrantApplicationService实例。我想我也可以传递一个ITitleService实例,但我尝试只将应用程序服务传递给相应的控制器。希望这有意义?@Brendan,我误读了这个问题,似乎
    标题
    用于下拉列表,而SelectedTitle是必填字段。您可能需要以某种方式保留表单上的信息,或者正如您所说的,在模型状态无效时,使用ITitleService在出现错误时重新填充标题。@Darin:前几天您提到聚合,这是什么意思?如果需要填充AccountTypes列表,现在会发生什么?我对AccountTypeService.GetAll和TitleService.GetAll都有一个服务方法。我应该在grantApplicationService中复制这两种方法吗?“对我来说,这听起来是不必要的。”布伦丹·沃格特,在不了解你的情况下很难回答这样的问题。这些
    账户
    标题
    实体之间是否存在任何关系?是什么使您有理由选择两种服务类别:
    AccountTypeService
    titleservice
    ?我觉得你在复制你的存储库。@Darin:我已经更新了我的帖子,并添加了一个更新部分。如果我需要提供更多的代码,请告诉我。@Brendan Vogt,编写一个服务方法,返回包含3个集合属性(标题、银行和帐户类型)的模型如何。然后在服务方法返回的模型和控制器中的视图模型之间设置映射。@Darin:我遇到的另一个问题是当ModelState.IsValid为false时,我的3个列表为null,这意味着需要重新填充它。考虑到已经包含表单值的视图模型,我需要如何以及在何处重新填充这些列表(根据上面的答案)?如果你能提供一些代码,那么将不胜感激。
    <% foreach(Title title in Model.Titles { %>
      <%: Html.HIddenFor(m => title) %>
    <% } %>
    
    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");
    }