在 HttpPost 上的验证失败后,我的 ViewModel 没有得到适当的补水,导致在重新显示视图时,'CartItems' 上出现“对象引用未设置为对象的实例”错误。
如何重新水化我的 ViewModel 以便它可以重新显示错误消息?
我曾尝试使用@Html.HiddenFor(...)
来保留未显示的值(根据此答案),但这不起作用。
视图模型
public class CheckoutViewModel
{
public List<Cart> CartItems { get; set; }
[DisplayFormat(DataFormatString = "${0:F2}")]
public double CartTotal { get; set; }
public virtual Order Order { get; set; }
}
控制器 GET:ActionResult
//GET: /Checkout/AddressAndPayment
public ActionResult AddressAndPayment()
{
var order = new Order();
order.Username = User.Identity.Name;
MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
storeDB.SaveChanges();
var cart = ShoppingCart.GetCart(this.HttpContext);
// Set up the ViewModel
var viewModel = new CheckoutViewModel
{
CartItems = cart.GetCartItems(),
CartTotal = cart.GetTotal(),
Order = order
};
// Return the view
return View(viewModel);
}
控制器 POST:ActionResult
[HttpPost]
public ActionResult AddressAndPayment(CheckoutViewModel checkoutViewModel)
{
TryValidateModel(checkoutViewModel);
try
{
checkoutViewModel.Order.Username = User.Identity.Name;
checkoutViewModel.Order.OrderDate = DateTime.Now;
storeDB.Orders.Add(checkoutViewModel.Order);
// Error occurs on the following line if a custom data annotation validation attribute fails
storeDB.SaveChanges();
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.CreateOrder(checkoutViewModel.Order);
storeDB.SaveChanges();
return RedirectToAction("Complete", new { id = checkoutViewModel.Order.OrderID });
}
catch
{
//Invalid - redisplay with errors
return View(checkoutViewModel);
}
}
编辑#1
@SoWeLie 告诉我,我已经解决了这个问题。
为了在将 ViewModel 中的 cartItem 重新水化,然后将其传递回 View,我将以下代码添加到了 HttpPost ActionResult 的 catch 块中。这段代码基本上调用了命中数据库的方法来获取购物车的必要信息:
catch
{
//Invalid - redisplay with errors
//The model is not valid, we need to redisplay the same view so that the user can fix the errors => fetch the cartItems
var cart = ShoppingCart.GetCart(this.HttpContext);
checkoutViewModel.CartItems = cart.GetCartItems();
checkoutViewModel.CartTotal = cart.GetTotal();
return View(checkoutViewModel);
}