This is the cshtml code, with the fields where user can input their order details. I also have the issue when I click on the place order button, I'm being redirected to empty cart page, with the error message "Your cart is empty".
The place order button should just trigger the method to save the user inputted fields to order database table, and the cart items as order items to the orderItem table.
<h1>Cart</h1>
@if (TempData["ErrorMessage"] != null)
{
<div class="alert alert-danger">@TempData["ErrorMessage"]</div>
}
@if (Model.Cart == null || Model.Cart.Items == null || Model.Cart.Items.Count == 0)
{
<p>Your cart is empty.</p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var cartItem in Model.Cart.Items)
{
<tr>
<td>@Model.GetPerfumeName(cartItem.PerfumeID)</td>
<td>
<form method="post" asp-page-handler="Update" asp-route-perfumeID="@cartItem.PerfumeID">
<div class="input-group">
<input type="number" class="form-control" name="quantity" value="@cartItem.Quantity" min="1" />
<div class="input-group-append">
<button type="submit" class="btn btn-primary">Update</button>
</div>
</div>
</form>
</td>
<td>@Model.GetPerfumePrice(cartItem.PerfumeID).ToString("C")</td>
<td>€@(Model.GetPerfumePrice(cartItem.PerfumeID) * cartItem.Quantity)</td>
<td>
<form method="post" asp-page-handler="Remove" asp-route-id="@cartItem.CartItemID">
<button type="submit" class="btn btn-danger">Remove</button>
</form>
</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<th></th>
<th></th>
<th></th>
<th>Total:</th>
<th class="@(ViewData["DiscountApplied"] != null ? "discounted-price" : "")">
€@(ViewData["DiscountApplied"] != null ? ViewData["DiscountedTotalPrice"] : Model.TotalPrice).ToString("N2")
</th>
</tr>
</tfoot>
</table>
<h3>Discount Code</h3>
<form method="post" asp-page-handler="ApplyDiscount">
<div class="form-group">
<label for="discountCode">Discount Code:</label>
<input type="text" class="form-control" id="discountCode" name="DiscountedCode" asp-for="DiscountedCode" required>
</div>
<button type="submit" class="btn btn-primary">Apply Discount</button>
</form>
<h3>Order Details</h3>
<form method="post" asp-page="/Cart" asp-page-handler="OnPostPlaceOrder" class="needs-validation">
@Html.AntiForgeryToken()
<div class="form-group">
<label for="shippingAddress">Shipping Address:</label>
<input type="text" class="form-control" id="shippingAddress" name="ShippingAddress" asp-for="Order.ShippingAddress" required>
<span asp-validation-for="Order.ShippingAddress" class="text-danger"></span>
</div>
<div class="form-group">
<label for="shippingCity">Shipping City:</label>
<input type="text" class="form-control" id="shippingCity" name="ShippingCity" asp-for="Order.ShippingCity" required>
<span asp-validation-for="Order.ShippingCity" class="text-danger"></span>
</div>
<div class="form-group">
<label for="shippingState">Shipping State:</label>
<input type="text" class="form-control" id="shippingState" name="ShippingState" asp-for="Order.ShippingState" required>
<span asp-validation-for="Order.ShippingState" class="text-danger"></span>
</div>
<div class="form-group">
<label for="shippingZipCode">Shipping Zip Code:</label>
<input type="text" class="form-control" id="shippingZipCode" name="ShippingZipCode" asp-for="Order.ShippingZipCode" required>
<span asp-validation-for="Order.ShippingZipCode" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Place Order</button>
</form>
</style>
This is the page model, where the OnPostPlaceOrder isn't working neither getting triggered with a breakpoint.
using DataAccesLayer5;
using DataAccessLayer5;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using SharedClassesLibrary5;
using System.Security.Claims;
namespace WebApplication30.Pages
{
public class CartModel : PageModel
{
public CartManager _cartManager;
private readonly OrderManager _orderManager;
private readonly DiscountCodeManager _discountCodeManager;
public decimal DiscountedPercentage { get; set; }
[BindProperty]
public string DiscountedCode { get; set; }
[BindProperty]
public Cart Cart { get; private set; }
[BindProperty]
public Order Order { get; private set; }
[BindProperty]
public string ShippingAddress { get; set; }
[BindProperty]
public string ShippingCity { get; set; }
[BindProperty]
public string ShippingState { get; set; }
[BindProperty]
public string ShippingZipCode { get; set; }
public int CustomerID { get; private set; }
public decimal TotalPrice { get; private set; }
public CartModel()
{
var connectionFactory = new DbConnectionFactory();
var cartRepository = new CartRepository(connectionFactory);
var orderRepository = new OrderRepository(connectionFactory);
var discountCodeRepository = new DiscountCodeRepository(connectionFactory);
_cartManager = new CartManager(cartRepository, _discountCodeManager);
_discountCodeManager = new DiscountCodeManager(discountCodeRepository, _cartManager);
_orderManager = new OrderManager(orderRepository);
}
public IActionResult OnGet(int? customerID)
{
if (customerID == null)
return RedirectToLoginPage();
Cart = _cartManager.GetCart(customerID.Value);
if (Cart == null)
return RedirectToCartPage();
Cart.Items = _cartManager.GetCartItems(customerID.Value).ToList(); // Set the Cart.Items property
Order = _orderManager.GetOrder(customerID.Value); // Initialize the Order property
TempData["CustomerID"] = customerID.Value.ToString();
if (Cart.Items.Count == 0)
Cart.Items = _cartManager.GetCartItems(customerID.Value).ToList();
TotalPrice = _cartManager.CalculateTotalPrice(Cart);
TotalPrice = _discountCodeManager.ApplyDiscounts(TotalPrice);
return Page();
}
public IActionResult OnPostApplyDiscount()
{
var customerID = GetCustomerIDFromTempData();
if (customerID == null)
return RedirectToLoginPage();
var discountCode = _discountCodeManager.GetDiscountByCode(DiscountedCode);
if (discountCode == null)
{
TempData["ErrorMessage"] = "Invalid discount code.";
return RedirectToCartPage(customerID.Value);
}
Cart = _cartManager.GetCart(customerID.Value);
if (Cart == null)
return RedirectToCartPage(customerID.Value);
_cartManager.ApplyDiscountCode(customerID.Value, discountCode.Code);
var discountedTotalPrice = _cartManager.CalculateTotalPrice(Cart);
TempData["SuccessMessage"] = "Discount code applied successfully.";
Cart = _cartManager.GetCart(customerID.Value);
ViewData["DiscountApplied"] = "true";
ViewData["DiscountedTotalPrice"] = discountedTotalPrice.ToString("N2");
return RedirectToCartPage(customerID.Value);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult OnPostPlaceOrder()
{
var customerID = GetCustomerIDFromTempData();
if (customerID == null)
{
return RedirectToLoginPage();
}
var cartItems = _cartManager.GetCartItems(customerID.Value);
if (cartItems.Count() == 0)
{
return RedirectToCartPage(customerID.Value);
}
Cart = _cartManager.GetCart(customerID.Value);
var order = new Order
{
CustomerID = customerID.Value,
OrderItems = cartItems.Select(item => new OrderItem(0, 0, item.PerfumeID, item.Quantity, item.Price)).ToList(),
Cart = Cart,
ShippingAddress = Request.Form["ShippingAddress"],
ShippingCity = Request.Form["ShippingCity"],
ShippingState = Request.Form["ShippingState"],
ShippingZipCode = Request.Form["ShippingZipCode"]
};
try
{
_orderManager.PlaceOrder(order);
_cartManager.ClearCart(customerID.Value);
return RedirectToOrderConfirmationPage();
}
catch (Exception ex)
{
TempData["ErrorMessage"] = "Failed to place the order. Please try again.";
return RedirectToCartPage(customerID.Value);
}
}
public IActionResult OnPostUpdate(int PerfumeID, int Quantity)
{
var customerID = GetCustomerIDFromTempData();
if (customerID == null)
{
return RedirectToLoginPage();
}
var cartItem = _cartManager.GetCartItem(customerID.Value, PerfumeID);
if (cartItem != null)
{
cartItem.Quantity = Quantity;
_cartManager.UpdateCartItem(cartItem);
}
return RedirectToCartPage(customerID.Value);
}
private IActionResult RedirectToOrderConfirmationPage()
{
return RedirectToPage("/Privacy");
}
private IActionResult RedirectToLoginPage()
{
return RedirectToPage("Login");
}
private IActionResult RedirectToCartPage(int? customerID = null)
{
return RedirectToPage("Cart", new { customerID });
}
private IActionResult RedirectToOrderHistoryPage(int? customerID = null)
{
return RedirectToPage("OrderHistory", new { customerID });
}
private IActionResult RedirectToCartPage(int customerID)
{
return RedirectToPage("/Cart", new { customerID = customerID });
}
private int? GetCustomerIDFromTempData()
{
if (TempData.ContainsKey("CustomerID") && int.TryParse(TempData["CustomerID"].ToString(), out int customerID))
{
return customerID;
}
return null;
}
public IActionResult OnPostRemove(int id)
{
var customerID = GetCustomerIDFromTempData();
if (customerID == null)
{
return RedirectToLoginPage();
}
_cartManager.RemoveCartItem(customerID.Value, id);
Cart = _cartManager.GetCart(customerID.Value);
return RedirectToCartPage(customerID.Value);
}
public IActionResult OnPostClear()
{
var userIdentity = User.FindFirst(ClaimTypes.NameIdentifier);
if (userIdentity == null || !int.TryParse(userIdentity.Value, out int userID))
{
return RedirectToPage("/Login");
}
if (TempData.ContainsKey("CustomerID") && int.TryParse(TempData["CustomerID"].ToString(), out int customerID))
{
_cartManager.ClearCart(customerID);
return RedirectToPage("/Cart", new { customerID = customerID });
}
return RedirectToCartPage();
}
public DiscountCode GetDiscountByCode(string code)
{
return _discountCodeManager.GetDiscountByCode(code);
}
public string GetPerfumeName(int perfumeID)
{
return _cartManager.GetPerfumeName(perfumeID);
}
public decimal GetPerfumePrice(int perfumeID)
{
return _cartManager.GetPerfumePrice(perfumeID);
}
`
I tried to add a debug line within the method self, but that didn't make hit either. Further I tried the things I already have in the code. I would appreciate a solution a lot!!
Handler methods in Razor Pages are methods that are automatically executed as a result of a request. The Razor Pages framework uses a naming convention to select the appropriate handler method to execute. The default convention works by matching the HTTP verb used for the request to the name of the method, which is prefixed with "On": OnGet()
, OnPost()
, OnPut()
etc.
So here the real name of OnPostPlaceOrder
method is PlaceOrder
, OnPost
just the Http verb means this method receive Post request, Just like [HttpPost]
attribute in MVC. When you use asp-page-handler
attribute you need to specify the real name which is PlaceOrder
.
asp-page-handler="PlaceOrder"
You can also refer to this Docs to learn more.