Part 16: Build a Complete "My Orders" History Tracking Page
Step 1: Implementing the User Order Retrieval Query
This code uses Entity Framework Core to fetch a customer's specific order rows while loading nested relational child details in a single database transaction wire call.
Core Mechanics & LINQ Query Breakdown
Eager Loading with Entity Framework Core (
.Includeand.ThenInclude): This is the most critical technical concept in this step. By default, EF Core uses lazy loading, meaning it won't fetch related tables unless explicitly told to..Include(o => o.OrderItems)explicitly instructs EF Core to join theOrderstable with theOrderItemstable..ThenInclude(oi => oi.Product)steps deep inside each child item to join theProductstable. This ensures that when your Razor view displays the history page, you can instantly print out the actual phone names (like@item.Product.Name) without causing a crash or triggering hidden, slow secondary queries.
Identity Filter Isolation (
.Where(o => o.UserId == userId)): This handles fundamental data isolation and application security. It ensures that the logged-in customer can only scan their own invoices, completely blocking unauthorized users from seeing other buyers' checkout details.Chronological Sorting Logic (
.OrderByDescending(o => o.OrderDate)): An essential e-commerce user experience pattern. This positions the user's newest transactions at the very peak of their history dashboard dashboard page, moving older orders further down the list.Non-Blocking Asynchronous Execution (
.ToListAsync()): By running this operation asynchronously with theawaitkeyword, you ensure that the database query execution thread is handed back to the server pool while waiting for SQL Server to return the records. This keeps your application fast and highly scalable under heavy traffic.
Step 2: Implementing the Orders History Controller Action
By placing this method inside the AccountController, you group it logically alongside other user-specific profile dashboards like address management or account settings.
Core Controller Mechanics Breakdown
The Security Guard Attribute (
[Authorize]): This is your primary defense line. The[Authorize]filter forces ASP.NET Core to intercept incoming requests before the method ever runs. If an anonymous user tries to manually visit/Account/Orders, the system automatically blocks them and redirects them straight to your Login page.Contextual Identity Resolution (
_userManager.GetUserAsync(User)): The globalUserproperty inside the controller represents the active browser's security principal (claims principal). By passing this context into the Identity Framework'sUserManager, the application decrypts the secure authentication cookie and extracts the corresponding user profile record from the database.Defensive Identity Fail-Safe:
if (user == null) return NotFound();Even with the
[Authorize]tag in place, this null-check acts as a critical backend guard rail. If a user deletes their account mid-session or their security token becomes corrupted, the system handles the anomaly gracefully by throwing an HTTP404 NotFoundresponse instead of crashing with a null reference exception.UI Header State Preservation:
ViewBag.CartItemCount = await _cartService.GetCartItemCountAsync();Since your viewers are navigating to a brand new view page, you must explicitly fetch and re-assign the cart count value to a dynamic property. This guarantees that your master layout header template keeps showing the correct, live shopping basket item bubble indicator while the customer views their order history.
Step 3: Explaining the "My Orders" Dashboard UI Layout
This template maps a strongly typed collection payload (List<Order>) into a responsive web structure using Bootstrap 5 UI standards and Bootstrap Icons (bi).
Core UI & Razor Syntax Design Breakdown
Two-Column Dashboard Grid Infrastructure (
col-lg-3&col-lg-9): The view establishes a classic modern e-commerce dashboard pattern.The Left Panel (
col-lg-3) houses a flush user-profile sidebar navigation menu, adding an.activeCSS class indicator onto the My Orders link.The Right Panel (
col-lg-9) operates as the primary workspace container, dynamically loading invoice datasets based on user state.
Defensive Empty-State Boundary Rendering:
@if (Model.Count == 0) { ... }If a new user accesses their dashboard without any past transactions, showing an empty data table looks unpolished. The view intercepts this state with an informative feedback container—complete with a
bi-bag-xcallout graphic and a descriptive navigation action button routing them back to your product catalog catalog.Advanced Razor C# Switch Expressions:
@(order.Status switch {OrderStatus.Pending => "bg-warning", OrderStatus.Processing => "bg-info", OrderStatus.Shipped => "bg-primary", OrderStatus.Delivered => "bg-success", OrderStatus.Cancelled => "bg-danger", _ => "bg-secondary" })Instead of utilizing messy nested conditional blocks, this implementation utilizes a modern C# relational pattern directly within the markup class attribute. This evaluates the system's
OrderStatusenum property value on the server, injecting matching contextual Bootstrap contextual class tokens (bg-success,bg-danger) to draw the customer's attention to their package shipping states instantly.Mobile-Friendly Layout Tables (
table-responsive): Standard HTML grid tables warp and overflow out of bounds on smartphone screens. Enclosing the table entity inside a.table-responsiveclass div layer instructs Bootstrap to automatically append a fluid horizontal swipe container, maintaining text clarity on smaller form factor screens.

Comments
Post a Comment