2012-04-24 23 views
1

私はコントローラとビューを使用して、ユーザーがショッピングカートの内容を「チェックアウト」できるようにしています。ViewModelがPOSTで更新されない

CheckoutControllerがOrderモデルをCheckoutビューに戻していたとき、すべて正常に機能していました。しかし、Checkoutビューにショッピングカートの内容を表示したいので、OrderとCartItemを含むビューモデルを使用するようにControllerとViewを変更しました。

私はCheckoutViewModelを作成し、このviewmodelを使用するためにGET:およびPOST:ActionResultsを変更しました。

問題はCheckOutViewModelが正しくPOST中に移入されていないです。

私はこの行のエラー「checkoutViewModel.Order.Username =ユーザー「オブジェクトのインスタンスに設定されていないオブジェクト参照」を取得しています。 Identity.Name; ' POST:ActionResultでは、しかし、私は何がinstansiatedされていない正確にはわかりません。

必要な場合は、CheckoutViewModelの代わりにOrederモデルを使用したオリジナルのコードを投稿することができます。

私はいくつかの単純な構造や構文の問題があると確信していますが、私はMVCの中で最良の方法で頭を尽くそうとしているからです。

GET:のActionResult

//GET: /Checkout/AddressAndPayment 
    public ActionResult AddressAndPayment() 
    { 
     //To pre-populate the form, create a new Order object and get the ShoppingCart, populate the ViewModel and pass it to the view 
     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 our ViewModel 
     var viewModel = new CheckoutViewModel 
     { 
      CartItems = cart.GetCartItems(), 
      CartTotal = cart.GetTotal(), 
      Order = order 
     }; 

     // Return the view 
     return View(viewModel); 
    } 

POST:のActionResult

 //POST: /Checkout/AddressAndPayment 
    [HttpPost] 
    public ActionResult AddressAndPayment(FormCollection values) 
    { 
     var checkoutViewModel = new CheckoutViewModel(); 
     TryValidateModel(checkoutViewModel); 

     try 
     { 
      checkoutViewModel.Order.Username = User.Identity.Name; 
      checkoutViewModel.Order.OrderDate = DateTime.Now; 
      //Save Order 
      storeDB.Orders.Add(checkoutViewModel.Order); 
      storeDB.SaveChanges(); 
      //Process the order 
      var cart = ShoppingCart.GetCart(this.HttpContext); 
      cart.CreateOrder(checkoutViewModel.Order); 
      storeDB.SaveChanges(); 
      //Send 'Order Confirmation' email 
      ViewData["order"] = checkoutViewModel.Order; 
      UserMailer.OrderConfirmation(checkoutViewModel.Order).SendAsync(); 

      return RedirectToAction("Complete", new { id = checkoutViewModel.Order.OrderID }); 
     } 
     catch 
     { 
      //Invalid - redisplay with errors 
      return View(checkoutViewModel); 
     } 
    } 

あなたはUはずビュー

@model OrderUp.ViewModels.CheckoutViewModel 
@{ 
    ViewBag.Title = "AddressAndPayment"; 
} 
<script src="../../Scripts/jquery-1.5.1.min.js" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> 

@using (Html.BeginForm()) { 
@Html.ValidationSummary(true) 
<h2>Pick Up Details</h2> 
<fieldset> 
    <legend>When are you gonna be hungry?</legend> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.Order.Phone) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.Order.Phone) 
     @Html.ValidationMessageFor(model => model.Order.Phone) 
    </div> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.Order.PickUpDateTime) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.Order.PickUpDateTime) 
     @Html.ValidationMessageFor(model => model.Order.PickUpDateTime) 
    </div> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.Order.Notes) 
    </div> 
    <div class="editor-multiline-field"> 
     @Html.EditorFor(model => model.Order.Notes) 
     @Html.ValidationMessageFor(model => model.Order.Notes) 
    </div> 
</fieldset> 
<input type="submit" value="Submit Order" /> 
} 
<div style="height:30px;"></div> 
<h3> 
    <em>Review</em> your cart: 
</h3> 
<table> 
<tr> 
    <th> 
     Menu Item 
    </th> 

    <th> 
     Price (each) 
    </th> 
    <th> 
     Notes 
    </th> 
    <th> 
     Quantity 
    </th> 
    <th></th> 
</tr> 
@foreach (var item in Model.CartItems) 
{ 
    <tr id="[email protected]"> 
     <td> 
      @Html.ActionLink(item.MenuItem.Name, "Details", "Store", new { id = item.MenuItemID }, null) 
     </td> 

     <td> 
      @Html.DisplayFor(modelItem => item.MenuItem.Price) 
     </td> 
     <td> 
      @Html.DisplayFor(modelItem => item.Notes) 
     </td> 
     <td id="[email protected]"> 
      @item.Count 
     </td> 
     <td> 
     </td> 
    </tr> 
} 
<tr> 
    <td > 
     Total 
    </td> 
    <td id="cart-total"> 
     @String.Format("${0:F2}", Model.CartTotal) 
    </td> 
    <td> 
    </td> 
    <td> 
    </td> 
    <td> 
    </td> 
</tr> 
</table> 
+0

私はあなたのデータベースに2つの別々のセーブをしているので、ここでは小さな変更を提案します - トランザクションでそれらをラップするため、2番目のセーブが失敗した場合は全メソッドをロールバックし、一貫性のない状態。 –

答えて

2

CheckoutViewModelをHttpPostメソッドの入力パラメータとして使用し、デバッグを試して、そのモデルがフォームポストの後にまだ格納されていないかどうかを確認します。

[HttpPost] 
    public ActionResult AddressAndPayment(CheckOutViewModel checkoutViewModel) 
    { 
     TryValidateModel(checkoutViewModel); 

     try 
     { 
      checkoutViewModel.Order.Username = User.Identity.Name; 
      checkoutViewModel.Order.OrderDate = DateTime.Now; 
      //Save Order 
      storeDB.Orders.Add(checkoutViewModel.Order); 
      storeDB.SaveChanges(); 
      //Process the order 
      var cart = ShoppingCart.GetCart(this.HttpContext); 
      cart.CreateOrder(checkoutViewModel.Order); 
      storeDB.SaveChanges(); 
      //Send 'Order Confirmation' email 
      ViewData["order"] = checkoutViewModel.Order; 
      UserMailer.OrderConfirmation(checkoutViewModel.Order).SendAsync(); 

      return RedirectToAction("Complete", new { id = checkoutViewModel.Order.OrderID }); 
     } 
     catch 
     { 
      //Invalid - redisplay with errors 
      return View(checkoutViewModel); 
     } 
    } 
+0

パーフェクト!ありがとう@MoXplod。それはそれを修正した。 を使用してViewModelが自動的に戻されるかどうかはわかりませんでした。 – Dhaust

関連する問題