2012-05-09 6 views
0

私の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); 
     } 

答えて

1

:このコードは、基本的には、カートのために必要な情報を取得するためにDBを打つメソッドを呼び出します。すべてのデータをポスト値として持ち歩こうとすると、保守が非効率で難しくなります。カートのオブジェクトは、データベースなどのアプリケーション内のどこかに永続化する必要があります。ユーザーのセッションでカートを保管することもできます。

これを達成する最良の方法は、ユーザーのカートをデータベースに保存することです。これを行うにはいくつかの方法があります。データベースモデルを知らなければ、最も簡単な解決策はカートとそのアイテムをデータベースに追加し、カートIDを取得してセッションまたはクッキーに保存することです(カートをどれくらい長く保存するかによって異なります)。

+0

オブジェクト全体を永続させるのは悪い考えです。問題はcartItemsが親Orderを必要とするOrderDetailモデルとしてデータベースに格納されており、それがDBに保存されないようにvailidationに失敗した注文です。したがって、関連するcartItemの親Orderは存在しません。彼らは外部キー違反を蹴る。 – Dhaust

+1

はい、オーダーにプロモートする前に、それらをCartおよびCartItemとしてデータベースに保存する必要があります。ユーザーがそれらをカートに追加すると、データベースに挿入されます。ユーザーが注文を送信すると、CartおよびCartItemをOrderおよびOrde​​rItemに移行することができます。 – SoWeLie

+0

あなたは正しいです。 viewModelをビューに返す前に、DBからviewModelのcartItemを再設定して、完全に機能しました。それを通して私に話してくれてありがとう。 – Dhaust

関連する問題