Welcome to Part 12 of our advanced series: Build a Full Mobile Shop E-Commerce Website in ASP.NET Core MVC! 🚀
In this tutorial, we are implementing an essential e-commerce feature that builds customer trust: a complete Product Review and Star Rating System. You will learn how to build the backend logic and frontend UI to allow authenticated users to submit reviews, leave star ratings, and display them dynamically on the product details page using Entity Framework Core.
Step 1: Creating the ReviewViewModel Grouping
By adding this class inside ProductViewModel.cs, you are organizing your code by context, ensuring that any view utilizing a product can easily access the review structure.
Core Properties & Validation Breakdown
Rating (The Star Value):
public int Rating { get; set; }The combination of[Required]and[Range(1, 5)]enforces strict data integrity. It ensures the user must actively pick a score, and blocks malicious requests trying to insert invalid ratings (like 0 or 100 stars) into your system before the database is even hit.Title (Brief Header):
public string? Title { get; set; }The nullable string (string?) means a headline is optional, giving flexibility to users who just want to leave a quick score. The[StringLength(100)]attribute caps the length, keeping your UI titles clean and your database safe from massive string overflows.Comment (The Detailed Body):
public string? Comment { get; set; }Like the title, this is optional, allowing users to submit ratings without words. The[StringLength(1000)]attribute provides a generous yet safe limit for thorough customer feedback without risking database text-bloat.
Step 2: Implementing the Product Reviews Interface inside Tabs
This code block integrates directly into your tab panels in the Product Details View, instantly adding interactive capabilities beneath your hardware specifications.
Core Components & Razor Logic Breakdown
Conditional Submission Access (
User.Identity?.IsAuthenticated): This check acts as a strict user gate. If the user is logged in, they are shown a clean, structured review form. If they are a guest, the form is replaced by a Bootstrapalert-infobox with a direct link to the login page. This guarantees that anonymous users cannot spam your database.Reverse Loop for CSS Star Rating Control:
@for (int i = 5; i >= 1; i--)Running the loop in reverse (from 5 down to 1) is a classic web development strategy. It allows CSS sibling selectors (
~) to properly highlight preceding stars when a user hovers over an option, creating a smooth, responsive desktop star selection interface.Approved Content Filtering (
Where(r => r.IsApproved)): This clause filters content at the database rendering level. By only displaying reviews whereIsApprovedis true, you protect your storefront from immediate offensive content or spam, giving you an administrative layer of control.Dynamic Rating Indicator Generation: The internal loop calculates and fills star icons on the fly for existing comments. If a review has a score of 4, the ternary operator outputs
bi-star-fillfour times andbi-star(the empty outline icon) for the remaining spot, giving customers an immediate visual summary.The Verified Purchase Trust Element: The badge check adds massive credibility to your app. If the backend flag detects the active user has a completed order invoice matching this product ID, it applies a green badge stating "Verified Purchase," a hallmark of elite storefront setups.
Step 3: Implementing the AddReviewAsync Service Method
This asynchronous method safely handles the business rules of map-transforming your user's form submission data into a permanent database record.
Core Logic & Architectural Breakdown
Defensive Existence Verification:
var product = await _context.Products.FindAsync(productId);Before executing any database writes, the code runs a verification check to ensure the targeted smartphone actually exists in your catalog. If a bad or manipulated product ID is requested, the service layer instantly cuts off execution and safely returnsfalse.Separation of Concerns Mapping: The code acts as a translator, mapping properties directly from your incoming
ReviewViewModelover to your backendReviewdatabase tracking entity. This translation layer keeps your presentation data safely insulated from your core data storage engine.Smart Business Control Flag (
IsApproved = true): SettingIsApproved = trueallows reviews to pass directly onto your digital storefront for now. This is a great placeholder tactic for tutorials; you can easily mention to your viewers that this flag can later be tied to an Admin approval toggle screen to fight spam bots.Optimized Async Performance: By leveraging
AddandSaveChangesAsync(), this operation runs entirely non-blocking. This means your online store remains incredibly responsive, scaling effortlessly even if hundreds of users are dropping feedback on hot products at the exact same moment.
Step 4: Implementing the AddReview Controller Action (HTTP POST)
By placing this AddReview method in your ProductController, you keep the endpoint intuitively aligned with product features. This structure facilitates easy routing and seamless view updates.
Core Components & Logic Breakdown
Strict Validation Gating (
ModelState.IsValid): The method instantly checks if incoming data matches the rules defined in your nestedReviewViewModel(e.g., verifying the rating is between 1 and 5). If validation fails, it records a helpful message intoTempDataand routes the user straight back to the item page without touching your database.Secure Identity Resolution via Identity:
var user = await _userManager.GetUserAsync(User);Instead of trusting a user ID passed invisibly inside a hidden form field—which can easily be altered by malicious users—this line securely grabs the user's authentic profile straight from the encrypted cookie context.Cross-Request Messaging via
TempData:TempDatais used here rather than a standardViewBagbecause the action finishes by redirecting the user to a different route (RedirectToAction).TempDatautilizes session storage behind the scenes to survive this redirect, letting you show clean, green success alerts on the newly loaded target page.Clean Return PRG (Post-Redirect-Get) Pattern: Ending with
RedirectToAction(nameof(Details), ...)is an important web development best practice. It prevents the annoying "Resubmit Form Data" popup that happens if a customer manually refreshes their browser after submitting a comment, completely optimizing the user journey.
Step 5: Hydrating the Wishlist State on Product Details View
This code runs when a user clicks on a product card to view its full details. It acts as an internal check to see if the filled heart or empty heart icon should be rendered.
Core Components & Logic Breakdown
Safe Identity Boundary Check:
if (User.Identity?.IsAuthenticated == true)This wrapper ensures that your code doesn't waste precious server resources running database lookups for guest shoppers. If the visitor is not logged in, it skips the check entirely, keeping the page loading instantly for unauthenticated traffic.Contextual User Resolution:
var user = await _userManager.GetUserAsync(User);Just like in your POST methods, this queries the official ASP.NET Core Identity store to grab the full profile data of the logged-in user, including their related tables.LINQ Collection Evaluation (
.Any):user?.WishlistItems.Any(w => w.ProductId == id) ?? false;Instead of writing a complex SQL query manually, you use LINQ to scan through the user'sWishlistItemscollection. If a row exists where theProductIdmatches the current product'sid, it returnstrue.The Null-Coalescing Fallback (
?? false): The?? falseoperator is a professional defensive coding practice. If the user object or the collection returns null for any reason, it safely defaults theisInWishlistvariable tofalseinstead of throwing a dangerousNullReferenceExceptionerror that could crash the page.

Comments
Post a Comment