难以在帖子上重新填充视图模型

时间:2014-05-08 14:36:28

标签: asp.net-mvc

我有各种viewmodel,它们具有必须填充的属性。例如,想象一个充满国家的数据库表。我有一个创建用户页面,viewmodel上的一个属性是List<string> Countries

最初我在无参数构造函数中填充了这个,即

public CreateUserViewModel()
{
   this.Countries = new CountryManager().GetCountries();
}

但我读到这是一个不好的做法,我应该把它们传入。

public CreateUserViewModel(IEnumerable<string> countries)
{
   this.Countries = countries;
}

但是在我的帖子中,这些数据丢失,如果验证失败,它会重定向到视图,但那时countries属性为null。

我想知道我应该如何重新填充这个值。手动将一些代码放入控制器post方法似乎很糟糕,例如。

[HttpPost]
public ActionResult CreateUser(CreateUserViewModel vm)
{
  if (Model.IsValid)
  {
      new UserManager().CreateUser(vm);
  }
  else
  {
     vm.Countries = new CountryManager().GetCountries();
     return View(vm);
  }
}

我正在努力谷歌这可能是一个非常常见的问题。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

避免无参数构造函数背后的基本原理是控制反转。在这种情况下,逻辑是Countries是一个依赖项,并且通过外化该依赖项(以便它被注入到类中),您可以使您的类更不易碎并且更容易扩展。

然而,我认为实际上并不适用于你的场景,因为Countries并不是你班级的依赖,而是你的视图。视图模型用于提供视图,并且在某种程度上是封闭的,不可扩展的无论如何。换句话说,请遵循服务,存储库,实用程序类等内容的控制反转,但对于视图模型,它并不是真正必要或重要的。

无论如何,这是我如何处理这类事情:

public class FooViewModel
{
    ...

    // Countries is not initialize by a constructor
    public IEnumerable<SelectListItem> Countries { get; set; }
}

然后在你的控制器中:

public class FooController : Controller
{
    internal void PopulateCountryChoices(FooViewModel model)
    {
        // fetch countries
        model.Countries = countries.Select(m => new SelectListItem
        {
            Text = m.Name,
            Value = m.Id.ToString()
        });
    }

    public ActionResult Bar()
    {
        var model = new FooViewModel();
        PopulateCountryChoices(model);
        return View(model);
    }

    [HttpPost]
    public ActionResult Bar(FooViewModel model)
    {
        if (ModelState.IsValid)
        {
            // save and redirect
        }

        PopulateCountryChoices(model);
        return View(model);
    }
}

答案 1 :(得分:1)

我们可以在视图中填充Dropdownlist值,而不是在模型中填充此静态数据 -

@Html.DropDownListFor(model => model.State, 
                      new SelectList(Utils.GetCountries()),
                      "value",
                      "text",
                      2)

其中Utils是一个返回所有国家的助手类。

这种填充所有静态数据的方式(我的意思是Dropdownlist或Listbox等的所有选项)都将由View接管,这使得模型可以免于保存这些数据。