0

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);
        }
4

1 に答える 1

2

CartItemのリストなどのオブジェクト全体を非表示フィールドに永続化することは望ましくありません。投稿値としてすべてのデータを持ち運びしようとすると、非効率的で維持が困難になります。カートオブジェクトは、データベースなどのアプリケーション内のどこかに永続化する必要があります。カートをユーザーのセッションに保存することもできます。

これを実現するための最良の方法は、ユーザーのカートをデータベースに保存することです。これを行うにはいくつかの方法があります。データベースモデルがわからない場合、最も簡単な解決策は、カートとそのアイテムをデータベースに追加し、カートIDを取得して、セッションまたはCookieのいずれかに保存することです(カートを保持する期間によって異なります)。

于 2012-05-09T01:11:12.150 に答える