ASP.NET MVC:使用相同的ViewModel呈现页面并获取结果

时间:2009-11-13 14:24:49

标签: asp.net-mvc

这是我使用的简单视图模型:

public class ViewModel
{
  public Order Order { get; set; }
  // returned from page - also can be pre-selected
  public string[] SelectedProducts { get; set; }
  // data for page to render available products to select from
  public IList<ProductViewModel> AvailableProducts { get; set; }
}

public ActionResult Edit(Order order)
{
   return View(new ViewModel { Order = order, SelectedProducts = new string[0], AvailableProducts = repository.GetAvailable() });
}

(请注意,订单在POST时由自定义模型绑定器自动绑定)

现在,我确实返回View(新的ViewModel(...))并且它可以工作。 GET / Edit页面呈现可用产品,用户选择它们,然后提交从SelectedProducts中选择的POST / Edit动作选择。

问题是当用户输入无效时 - 我需要在不触及输入的用户数据的情况下重新显示页面,同时仍提供AvailableProducts。只有返回视图(数据)将无效,因为AvailableProducts不是提交数据的一部分,并且为空。

问题是:我该如何解决问题?我能做到

public ActionResult(ViewModel data)
{
   if (!ModelState.IsValid)
   {
      data.AvailableProducts = repository.GetAvailable();
      return View(data);
   }
}

但它有点冗长,并且容易出错,因为提交的属性和要重置的属性并不明显。还有更好的方法吗?

例如,我可以让ViewModel自己获取数据(例如使用ServiceLocator)但这并不好,因为控制器应该准备数据。

2 个答案:

答案 0 :(得分:3)

我不知道有更好的方法,但你可能想把它重构为一个可以被两个动作重用的单独方法。

private ViewModel PopulateModelForView( Order order, string[] products )
{
     return new ViewModel
            {
                Order = order,
                SelectedProducts = products ?? new string[],
                AvailableProducts = repository.GetAvailable()
            };
}

public ActionResult Edit(Order order)
{
   return View( PopulateModelForView( order, null) );
}

public ActionResult Update(ViewModel data)
{
   if (!ModelState.IsValid)
   {
      return View( PopulateModelForView( data.Order, data.SelectedProducts ) );
   }
}

答案 1 :(得分:0)

我所做的只是创建一个新的视图,将输入的输入作为参数。那就是:

public ActionResult Create([Bind(Exclude = "Id")]Profiles profileToAdd)
{
        try{
            your shiny code here
        }
        catch{
            return View(new ProfileFormViewModel(profileToAdd));
        }
}

这会使未正确填充的位置显示为红色,而其他位置则已正确设置。我不知道这是不是你要找的?

在您的情况下,您可以让列表作为输入进入方法或再次生成。随你喜欢。然后通过您的viewmodel(已编辑)再次发送:

public ActionResult Create(Order order, IList<ProductViewModel> AvailableProducts)
{
        try{
            UpdateModel(order);
            SaveChanges();
        }
        catch{
            return View(new ViewModel(order, AvailableProducts));
        }
}