In Part 17, we are reaching the most critical phase of our Food Ordering System: the Checkout Process. This is where your users' shopping experience turns into a real business transaction. The HttpGet Checkout method is the entry point that prepares the final bill and ensures the user is ready to pay.
Step-by-Step Code Explanation
Authentication Guard: The code first checks the session for a
UserId. If the user isn't logged in, it redirects them to the Login page. You can't place an order if the system doesn't know who is paying!Cart Verification: We call
GetCart()to see what’s inside. If the cart is empty (!cart.Any()), it redirects the user back to the Menu. This prevents "Ghost Orders" where a user might accidentally try to checkout with zero items.Dynamic Total Calculation:
cart.Sum(c => c.Price * c.Quantity): This logic uses LINQ to iterate through every item in the cart, multiply its price by the quantity, and calculate the grand total.
ViewBag Data Transfer: We store that final sum in
ViewBag.Total. This allows us to display the "Grand Total" on the checkout page so the customer knows exactly how much they are spending before they confirm.
[HttpGet]
public IActionResult Checkout()
{
var userId = HttpContext.Session.GetInt32("UserId");
if (userId == null) return RedirectToAction("Login", "Account");
var cart = GetCart();
if (!cart.Any()) return RedirectToAction("Index", "Menu");
ViewBag.Total = cart.Sum(c => c.Price * c.Quantity);
return View();
}
We are designing the interface that bridges the gap between a digital shopping cart and a real-world delivery. This Checkout View is intentionally streamlined to reduce "cart abandonment"—asking only for the essential details needed to get the food from the kitchen to the customer's door.
Step-by-Step Code Explanation
ViewBag.TotalDisplay: We pull the calculated sum from the controller and display it prominently in analert-infobox. This ensures the customer has a final look at the price before committing to the purchase.The Delivery Address (
textarea): Instead of a simple input, we use atextareawithrows="3". This gives the user enough space to include apartment numbers, street names, or specific delivery instructions (like "leave at the front gate").Phone Number Input: By using
type="tel", we optimize the form for mobile users, triggering the numeric keypad on smartphones for a smoother user experience.Form Submission: The
<form>tag usesmethod="post"and points to our/Order/Checkoutaction. Thenameattributes (deliveryAddressandphoneNumber) are critical, as they must match the parameters in our upcoming C# POST method.Bootstrap 5 Styling:
card shadow: Gives the checkout form a professional, elevated look.w-100 btn-lg: Makes the "Place Order" button large and full-width, making it the clear primary action on the page.
@{
ViewData["Title"] = "Checkout";
}
<div class="container my-5">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card shadow">
<div class="card-header bg-primary text-white">
<h4 class="mb-0"><i class="bi bi-credit-card"></i> Checkout</h4>
</div>
<div class="card-body">
<div class="alert alert-info">
Total Amount: <strong>$@ViewBag.Total</strong>
</div>
<form action="/Order/Checkout" method="post">
<div class="mb-3">
<label class="form-label">Delivery Address</label>
<textarea name="deliveryAddress" class="form-control" rows="3" required></textarea>
</div>
<div class="mb-3">
<label class="form-label">Phone Number</label>
<input type="tel" name="phoneNumber" class="form-control" required />
</div>
<button type="submit" class="btn btn-primary w-100 btn-lg">
Place Order <i class="bi bi-check-circle"></i>
</button>
</form>
</div>
</div>
</div>
</div>
</div>
we are implementing the "engine" of our e-commerce platform: the Checkout POST Method. This is the most important piece of code in the series, as it handles the logic of converting a temporary shopping cart into a permanent record in your SQL database.
Step-by-Step Code Explanation
Parameter Mapping: The method accepts
deliveryAddressandphoneNumberdirectly from the form we built in the previous step. These are passed into the method as strings.Order Object Creation: We initialize a new
Orderobject. This is where we link the user's ID, their contact info, and the final price.The
SelectProjection:cart.Select(...): This is a powerful LINQ command. It transforms your temporaryCartItemlist into a list ofOrderItemobjects that match your database schema.It captures the
FoodItemId,Quantity, andUnitPriceat the exact moment of purchase.
Database Persistence:
_context.Orders.Add(order): This adds the main order and all its child items (OrderItems) to the tracking context._context.SaveChanges(): This wraps everything in a single SQL Transaction, ensuring that if something fails, no partial data is saved.
Cart Cleanup: After a successful purchase, we call
HttpContext.Session.Remove("Cart"). This empties the user's bag so they can start a fresh order next time.Confirmation Redirect: Finally, we send the user to a "Thank You" page, passing the newly generated
orderIdso they can track their meal!
[HttpPost]
public IActionResult Checkout(string deliveryAddress, string phoneNumber)
{
var userId = HttpContext.Session.GetInt32("UserId");
var cart = GetCart();
var order = new Order
{
UserId = userId.Value,
DeliveryAddress = deliveryAddress,
PhoneNumber = phoneNumber,
TotalAmount = cart.Sum(c => c.Price * c.Quantity),
OrderItems = cart.Select(c => new OrderItem
{
FoodItemId = c.FoodItemId,
Quantity = c.Quantity,
UnitPrice = c.Price
}).ToList()
};
_context.Orders.Add(order);
_context.SaveChanges();
HttpContext.Session.Remove("Cart");
return RedirectToAction("OrderConfirmation", new { orderId = order.Id });
}
We reach the final destination of the user's shopping journey: the Order Confirmation. After the heavy lifting of saving data to the database, this method provides the "Digital Receipt" that gives users peace of mind that their delicious meal is on the way.
Step-by-Step Code Explanation
Parameter Passing: The method accepts an
int orderId. This ID is automatically generated by your SQL database during the_context.SaveChanges()call in the previous step and passed here via the redirect.ViewBag.OrderId: We store the unique ID in theViewBag. This allows us to display the specific order number (e.g., "Order #1024") directly on the webpage so the customer can use it for support or tracking.UI Feedback: The
return View()command loads the "Thank You" page. In a professional Food Ordering System, this is where you would usually show a success animation or a summary of the delivery time.
public IActionResult OrderConfirmation(int orderId)
{
ViewBag.OrderId = orderId;
return View();
}
we wrap up the entire purchasing workflow with the Order Confirmation View. This page is the "Final Reward" for the user—it confirms that their transaction was successful and provides them with their unique tracking number.
Step-by-Step Code Explanation
text-center&display-1: We use Bootstrap’s typography classes to create a "Hero" moment. The large green checkmark icon (bi-check-circle-fill) gives immediate visual confirmation that everything went right.border-success&shadow-lg: By adding a green border and a large shadow to the card, we make the success message feel premium and distinct from other pages in our Food Ordering System.Dynamic ID Display: We pull the ID we saved in the controller using
#@ViewBag.OrderId. This turns a generic "Thank You" into a personalized receipt.text-muted&lead: These helper classes manage the visual hierarchy, making the "Thank you" stand out while keeping the Order ID clearly legible.Call to Action (CTA) Buttons:
The "Continue Shopping" button (Primary) encourages the user to keep exploring the site.
The "Browse Menu" button (Outline) provides a secondary path back to the food listings.
@{
ViewData["Title"] = "Order Confirmed";
}
<div class="container my-5">
<div class="row justify-content-center">
<div class="col-md-6 text-center">
<div class="card shadow-lg border-success">
<div class="card-body py-5">
<i class="bi bi-check-circle-fill text-success display-1 mb-3"></i>
<h2 class="text-success mb-3">Order Placed Successfully!</h2>
<p class="lead">Thank you for your order.</p>
<p class="text-muted">Your Order ID: <strong>#@ViewBag.OrderId</strong></p>
<hr />
<p>We'll deliver your food soon. You can track your order status in your account.</p>
<div class="mt-4">
<a href="/" class="btn btn-primary me-2">Continue Shopping</a>
<a href="/Menu" class="btn btn-outline-primary">Browse Menu</a>
</div>
</div>
</div>
</div>
</div>
</div>
Comments
Post a Comment