Welcome to Part 30 of our series! Today we are tackle an essential database management and security pattern for our e-commerce platform: Soft Deletion.
In Step 1, we implement the secure HTTP POST Delete action method. Instead of executing a destructive SQL DELETE query that permanently erases data, this method flips a state flag to cleanly deactivate the product. This approach preserves historical database records, such as old customer order details, while instantly hiding the item from the storefront.
Here is the step-by-step breakdown of how this code functions.
Step 1: Implementing Soft Delete Logic
Hard Delete vs. Soft Delete Architecture
Step-by-Step Code Explanation
HTTP Verb Restriction & Token Verification
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id)
[HttpPost]: Restricts this action to accept onlyPOSTrequests. We never use an HTTPGETrequest for data mutations like deletions, as search engine web crawlers or malicious links could accidentally trigger them.[ValidateAntiForgeryToken]: Works alongside the@Html.AntiForgeryToken()we embedded inside our Step 2 form. It validates a secure, unique request token to block Cross-Site Request Forgery (CSRF) attacks.
Asynchronous Entity Verification
if (product == null)
return NotFound();
_context.Products.FindAsync(id): Uses Entity Framework Core's optimized primary key lookup method to efficiently locate the product record in memory or disk.if (product == null): If an unexpected tracking ID is passed, the server safely terminates the request and returns an HTTP 404 response.
State Manipulation (The "Soft Delete" Core)
product.IsActive = false;
Rather than running
_context.Products.Remove(product), which translates to a hard relational database removal statement, we modify theIsActivetracking boolean attribute.By updating this flag to
false, the product remains safely stored in our database records (preserving historical relationships like customer order items), but it will no longer pass query filters on the public user storefront layout.
Persistence, Session Notifications, and Routing
TempData["Success"] = "Product deleted successfully.";
return RedirectToAction(nameof(Index));
SaveChangesAsync(): Commits the state change tracking modifications asynchronously to SQL Server, generating an optimizedUPDATE Products SET IsActive = 0 WHERE Id = @idcommand behind the scenes.TempData["Success"]: Stores a short-lived notification message in the temporary session data container. This message will display on the subsequent view page load to provide feedback to the administrator.RedirectToAction(nameof(Index)): Clears the input submission pipeline and safely redirects the user's browser back to our main product management table view.
In Step 2 of Part 30, we are updating our Product Details View by integrating the front-end trigger for our soft delete mechanism. While this looks like a simple button on the outside, it is actually wrapped inside a secure, self-contained HTML form structure.
Here is the step-by-step breakdown of how this UI code safely passes data to the controller action we created in Step 1.
Step 2: Integrating the Secure Delete Form
The Secure Form Submission Pipeline
Step-by-Step Code Explanation
The Form Wrapper & Layout Attributes
asp-action="Delete": The ASP.NET Core Form Tag Helper automatically generates the correct routing URL targeting theDeleteaction method within the current controller.method="post": Explicitly sets the HTTP transfer protocol toPOST. This ensures the request maps perfectly to our backend[HttpPost]attribute and keeps critical mutation parameters out of the visible URL query string.class="d-inline float-end": Bootstrap 5 utility classes.d-inlineprevents the form from breaking onto a new line (allowing it to sit side-by-side with your Edit and Back buttons), whilefloat-endaligns it cleanly to the right edge of the card footer container.
Client-Side Safety Confirmation Interceptor
This uses native JavaScript to create an immediate UX safety net.
When an administrator clicks the button, the browser pauses execution and opens a modal confirmation dialogue box. If the user clicks Cancel, the script returns
false, instantly killing the form submission event before it ever hits your web server. If they click OK, it returnstrueand the request proceeds.
Cryptographic CSRF Protection Token
This injects a hidden cryptographic input element containing a unique request token generated by the server.
When the form is submitted, ASP.NET Core checks this token against a corresponding cookie on the server. If a malicious third-party site tries to trick an authenticated admin into clicking this link via a Cross-Site Request Forgery (CSRF) attack, the tokens will mismatch, and the system will safely block the request.
Hidden Record Context Payload
Because an administrative user doesn't need to see or edit the raw database primary key on the screen, we pass it using
type="hidden".The
name="id"attribute is critical—it matches the exact case-insensitive parameter input name (int id) defined in our backendDelete(int id)controller signature from Step 1, allowing model binding to pair them automatically.
Visual Styling & Action Trigger
<i class="fas fa-trash"></i> Delete
</button>
type="submit": Explicitly designates this button as the execution trigger for its parent form container.btn btn-danger: Applies Bootstrap's red alert accent coloring to clearly signal a high-consequence data mutation action.<i class="fas fa-trash"></i>: Injects a recognizable trash can glyph from Font Awesome to provide an intuitive visual cue.
In Step 3 of Part 30, we are bringing the soft delete functionality directly to our Product Index View (the main table layout). This allows administrators to quickly deactivate products straight from the inventory list without having to click into the details page first.
While this snippet shares the same backend routing and security logic as the button we placed in the details view, its styling and scope are optimized specifically to fit cleanly inside a compact table row (<td>).
Here is the step-by-step breakdown of how this inline form operates.
Step 3: Implementing Inline Row Deletion
The Tabular Action Layout Workflow
Step-by-Step Code Explanation
The Compact Form Wrapper
asp-action="Delete"&method="post": Just like before, this targets our secureHttpPostaction method in the controller, keeping our request safe from web crawlers.class="d-inline": Keeping the form display inline is vital inside a table cell. It ensures this delete button sits perfectly horizontal next to your Edit or Details link buttons instead of breaking down onto a new line and distorting the table row height.onsubmit="...": A shortened client-side JavaScript confirmation check ('Are you sure?') tailored to keep the modal pop-up prompt quick and efficient for rapid data management.
Loop-Context Hidden Input Binding
Notice the value expression here uses
@product.Idinstead of@Model.Id.Because this code lives inside a
@foreach (var product in Model)loop on your Index page, this hidden input ensures that whichever row the admin clicks, that specific product's iteration ID is accurately packed into the form payload.
Micro-UI Button Styling & Bootstrap Icons
<i class="bi bi-trash"></i>
</button>
btn-sm: Shrinks the padding and font size of the button to make it a small, professional component that scales properly within a dense data grid.btn-outline-danger: Applies a subtle, professional styling trick. The button appears with a transparent background and a red border, only flipping to solid red when hovered over. This keeps the index page clean and prevents it from looking overly cluttered with massive red blocks.<i class="bi bi-trash"></i>: Uses a Bootstrap Icon (bi) trash can glyph, matching the overall design aesthetic of your main administrative storefront layout.

Comments
Post a Comment