ModelState无效时保留下拉信息

时间:2014-03-14 13:32:02

标签: c# asp.net-mvc validation

我的DropDownLists存在一些问题,因为当我发布信息并且我的模型无效时,它会回到页面“空”,触发与this question完全相同的错误。

我已经使用了那里提出的解决方案,它解决了我的问题。无论如何,我想避免每当我的ModelState无效时查询数据库,我就采用这种方法。我想知道它是否有效或者现在是否有更好的方法来实现它,考虑到我没有使用MVC来代替MVC2(这是question的MVC版本),也许他们添加了解决这个问题的新方法。

我所做的是在我的模型无效时使用TempData来保存信息。

public class ViewModel
{
    [DisplayName("Project")]
    public int ProjectID { get; set; }
    public List<SelectListItem> Projects { get; set; }

    //Other fields
}

现在我的Create()动作(填充项目)

[HttpGet]
public ActionResult Create()
{
    ViewModel vmodel = new ViewModel();
    vmodel.Projects = db.GetProjects(User.Identity.Name).Select(x => new SelectListItem { Text = x.Description, Value = x.Id }).ToList();
    TempData["Projects"] = vmodel.Projects;

    return View(vmodel);
}

我的帖子就是这样的:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ViewModel vmodel)
{
    //Clear TempData (in theory will clear my tempdata when read, so if this controller redirects to another action my tempdata will be clear)
    List<SelectListItem> projects = (TempData["Projects"] as List<SelectListItem>);

    if (ModelState.IsValid)
    {
        //...
    }

    //If it got here it's going back to the screen.
    //Repopulate the TempData (allowing it to exist one more trip)
    TempData["Projects"] = projects;
    vmodel.Projects = projects

    return View(atendimento);
}

这种做法是好的吗?有没有更好的方法来实现这一目标而不是每次都查询数据库?

非常感谢!

2 个答案:

答案 0 :(得分:3)

您根本不需要使用TempData,因为视图模型中有属性来保存下拉项。

public ActionResult Create()
{
    ViewModel vmodel = new ViewModel();
    vmodel.Projects = GetProjects(); 
    return View(vmodel);
}
private List<SelectListItem> GetProjects()
{
     return db.GetProjects(User.Identity.Name)
                 .Select(x => new SelectListItem { Text = x.Description,
                                                   Value = x.Id }).ToList();   
}

在视图中

@Html.DropDownListFor(s=>s.ProjectID,Model.Projects)

在您的HttpPost操作中,如果ModelState无效,请再次重新加载Projects集合(因为http是无状态

if(ModelState.IsValid)
{
  // to do :Save and redirect
}
model.Projects = GetProjects(); 
return View(model);

您可以缓存Projects,这样如果您对性能过于担心,则无需每次都访问数据库。

答案 1 :(得分:1)

就个人而言,我不担心每次都要查询数据库进行此类操作。

如果添加/删除项目怎么办?这可能是保存失败(选定的项目被删除)以及用户永远不会意识到的原因。

我通常会编写一个方法来填充我的所有视图模型的SelectListItem,然后在我的GetPost中使用此方法,如果验证失败。