这是我使用的简单视图模型:
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)但这并不好,因为控制器应该准备数据。
答案 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));
}
}