英文:
OnPostPlaceOrder method isn't working, neither is it getting hit when I add breakpoint, it's like it doesn't exists, why?
问题
这是cshtml代码,用户可以在其中输入其订单详情。
当我点击“下订单”按钮时,出现问题,我被重定向到空的购物车页面,并显示错误消息“您的购物车为空”。
“下订单”按钮应该触发将用户输入的字段保存到订单数据库表以及将购物车项目保存为订单项目到orderItem表的方法。
@model WebApplication30.Pages.CartModel
<h1>购物车</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>您的购物车是空的。</p>
}
else
{
<table class="table">
<thead>
<tr>
<th>名称</th>
<th>数量</th>
<th>价格</th>
<th>总计</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">更新</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">移除</button>
</form>
</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<th></th>
<th></th>
<th></th>
<th>总计:</th>
<th class="@(ViewData["DiscountApplied"] != null ? "discounted-price" : "")">
€@(ViewData["DiscountApplied"] != null ? ViewData["DiscountedTotalPrice"] : Model.TotalPrice).ToString("N2")
</th>
</tr>
</tfoot>
</table>
<h3>优惠码</h3>
<form method="post" asp-page-handler="ApplyDiscount">
<div class="form-group">
<label for="discountCode">优惠码:</label>
<input type="text" class="form-control" id="discountCode" name="DiscountedCode" asp-for="DiscountedCode" required>
</div>
<button type="submit" class="btn btn-primary">应用优惠</button>
</form>
<h3>订单详情</h3>
<form method="post" asp-page="/Cart" asp-page-handler="OnPostPlaceOrder" class="needs-validation">
@Html.AntiForgeryToken()
<div class="form-group">
<label for="shippingAddress">送货地址:</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">送货城市:</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">送货州:</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">送货邮政编码:</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">下订单</button>
</form>
</style>
这是页面模型,在其中OnPostPlaceOrder方法没有起作用,也没有触发断点。
using BusinessLogicLayer5;
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
{
// 省略其他成员和方法,仅显示OnPostPlaceOrder方法
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult OnPostPlaceOrder()
{
// 此处省略其他代码
}
// 省略其他方法
}
}
如果OnPostPlaceOrder方法没有被触发,您可以确保以下几点:
-
确保您的cshtml页面中的“下订单”按钮的form元素的action属性指向正确的Page和PageHandler,以便触发OnPostPlaceOrder方法。
-
检查页面模型中的OnPostPlaceOrder方法是否与cshtml页面中的form元素中的asp-page和asp-page-handler属性匹配。
-
确保在页面加载时没有发生其他错误,导致页面无法正常显示或触发OnPostPlaceOrder方法。
如果您已经检查了以上几点并且问题仍然存在,您可以考虑添加日志记录或调试语句来进一步排查问题,以确定代码中的哪一部分出现了问题。
英文:
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!!
答案1
得分: 0
在Razor Pages中,处理程序方法是由于请求而自动执行的方法。Razor Pages框架使用命名约定来选择要执行的适当处理程序方法。默认约定通过将用于请求的HTTP动词与方法的名称匹配来工作,方法名称前缀为"On":OnGet()
,OnPost()
,OnPut()
等。
因此,在这里,OnPostPlaceOrder
方法的实际名称是PlaceOrder
,OnPost
只是HTTP动词,表示该方法接收POST请求,就像MVC中的[HttpPost]
属性一样。当您使用asp-page-handler
属性时,您需要指定实际名称,即PlaceOrder
。
asp-page-handler="PlaceOrder"
您还可以参考此文档以获取更多信息。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论