2012-04-24 3 views
1

У меня есть контроллер и просмотр, которые позволяют пользователю «проверять» содержимое корзины покупок.ViewModel не обновляется на POST

Все отлично работало, когда мой CheckoutController возвращал модель заказа в представление Checkout. Однако теперь я хочу также отображать содержимое корзины покупок в представлении «Копить», поэтому изменил «Контроллер» и «Вид», чтобы использовать модель просмотра, содержащую Order и CartItems.

Я создал CheckoutViewModel и изменил GET: и POST: ActionResults, чтобы использовать эту модель.

Проблема является CheckOutViewModel не должным образом заполняется во время процедуры POST:

Я получаю «ссылка на объект не указывает на экземпляр объекта» ошибки на этой линии «checkoutViewModel.Order.Username = User. Identity.Name;» в POST: ActionResult, но я точно не знаю, что не создается.

Если нужно, я могу опубликовать исходный рабочий код, который использовал модель Oreder вместо CheckoutViewModel.

Уверен, что у меня есть простая проблема со степенью или синтаксисом, я просто не могу сказать, что это такое, потому что я все еще пытаюсь найти лучший способ сделать что-то в 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 отдельными сохраняет в вашу БД - Для того, чтобы обернуть их в сделке, так что если второй бросок терпит неудачу всего метод может откатить и не оставить дб в несогласованное состояние. –

ответ

2

Вы должны у se 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

Смежные вопросы