HttpPostでの検証に失敗した後、ViewModelが適切に再水和されないため、ビューが再表示されているときに'CartItems'で'オブジェクト参照がオブジェクトのインスタンスに設定されていません'エラーが発生します。
ViewModelを再水和して、エラーメッセージとともに再表示できるようにするにはどうすればよいですか?
(この回答@Html.HiddenFor(...)
のように)表示されていない値を永続化するためにを使用しようとしましたが、これは機能しませんでした。
ViewModel
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のcartItemsを再水和するために、HttpPostActionResultのcatchブロックに次のコードを追加しました。このコードは基本的に、カートに必要な情報を取得するためにDBにヒットするメソッドを呼び出します。
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);
}