2012-04-24 72 views
1

我有一個控制器和視圖,允許用戶'檢出'購物車的內容。ViewModel不在POST上更新

當我的CheckoutController將Order模型返回到Checkout視圖時,所有工作都正常。但是,我現在還希望在Checkout視圖中顯示購物車的內容,因此修改了Controller和View以使用包含Order和CartItems的視圖模型。

我創建了一個CheckoutViewModel並修改了GET:和POST:ActionResults以使用此視圖模型。

問題是CheckOutViewModel未在POST期間被正確填充:

我收到這條線「checkoutViewModel.Order.Username =用戶錯誤的「未設置爲一個對象的實例對象引用」。 Identity.Name;」在POST:ActionResult中,但我不確定具體是什麼。

如果需要,我可以發佈使用Oreder模型代替CheckoutViewModel的原始工作代碼。

我確定我有一些簡單的sturctural或語法問題,我只是不能告訴它是什麼,因爲我仍然試圖讓我的頭在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); 
     } 
    } 

查看

@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個單獨保存到你的數據庫 - 要包裝他們在一個事務中,所以如果第二保存失敗的整個方法可以回滾,而不是讓你的數據庫中不一致的狀態。 – 2012-05-20 23:21:24

回答

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 2012-04-24 01:10:52