私のViewModelが正しくHttpPost「CartItems」にエラー「オブジェクトのインスタンスに設定されていないオブジェクト参照」になるに失敗した後vailidationを再水和されていません再表示されます。後のViewModelを再水和する方法HttpPost検証エラー表示がされているとき
ViewModelを再生成してエラーメッセージで再表示するにはどうすればよいですか?
@Html.HiddenFor(...)
を使用して表示されていない値を維持しようとしましたが(this answer)、これは機能しませんでした。
の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を再水和するには、次のコードをHttpPost ActionResultのcatchブロックに追加しました。あなたはこのような隠された分野でCartItemのリストとして全体のオブジェクトを永続化したいとは思わないでしょう
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);
}
オブジェクト全体を永続させるのは悪い考えです。問題はcartItemsが親Orderを必要とするOrderDetailモデルとしてデータベースに格納されており、それがDBに保存されないようにvailidationに失敗した注文です。したがって、関連するcartItemの親Orderは存在しません。彼らは外部キー違反を蹴る。 – Dhaust
はい、オーダーにプロモートする前に、それらをCartおよびCartItemとしてデータベースに保存する必要があります。ユーザーがそれらをカートに追加すると、データベースに挿入されます。ユーザーが注文を送信すると、CartおよびCartItemをOrderおよびOrderItemに移行することができます。 – SoWeLie
あなたは正しいです。 viewModelをビューに返す前に、DBからviewModelのcartItemを再設定して、完全に機能しました。それを通して私に話してくれてありがとう。 – Dhaust