In Part 16 of our Food Ordering System series, we tackle a critical security feature: Change Password Logic in ASP.NET Core MVC. You will learn how to create a secure ChangePasswordViewModel, implement Data Annotations for complex password validation, and write the Controller Action to verify the existing password before updating the database. We also show how to use Entity Framework Core for secure data persistence and Bootstrap 5 for a professional user interface. Secure your C# Web Application today!
In Part 16, we begin the implementation of a vital security feature: the Change Password functionality. While this code looks simple, it serves as the essential "Gatekeeper" that serves the user interface to our customers.
Step-by-Step Code Explanation
[HttpGet]Attribute: This decorator tells the ASP.NET Core routing system that this method should only respond to "GET" requests (when a user clicks a link or types the URL). It is the "Request for the Page" phase.The Action Method:
public IActionResult ChangePassword()is the controller action responsible for initializing the password update process.return View(): This command tells the engine to look for a file namedChangePassword.cshtmlin theViews/Accountfolder. Since we aren't passing a model yet, it simply loads the empty form for the user to fill out.
[HttpGet]
public IActionResult ChangePassword()
{
return View();
}
We are building the backbone of our security update: the ChangePasswordViewModel. In any professional ASP.NET Core MVC application, we never pass raw data to the controller. Instead, we use a ViewModel to enforce strict validation rules, ensuring that the user's new password is secure and correctly typed.
Step-by-Step Code Explanation
[DataType(DataType.Password)]: This is a vital attribute. It tells the browser to mask the input (showing dots instead of characters), ensuring privacy while the user types.The Current Password: Before allowing a change, we require the
CurrentPassword. This prevents unauthorized changes if a user leaves their account logged in on a public computer.Password Strength (
StringLength): We enforce a security rule where theNewPasswordmust be at least 6 characters long and no more than 100. This protects your Food Ordering System from "weak" passwords.The Compare Attribute: This is the most powerful part of the code.
[Compare("NewPassword")]automatically checks if theConfirmPasswordmatches theNewPassword. If they don't match, the system will show an error message instantly without even hitting the database.
public class ChangePasswordViewModel
{
[Required]
[DataType(DataType.Password)]
[Display(Name = "Current Password")]
public string CurrentPassword { get; set; }
[Required]
[StringLength(100, MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "New Password")]
public string NewPassword { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm New Password")]
[Compare("NewPassword")]
public string ConfirmPassword { get; set; }
}
we are designing the frontend for the password security module. This Razor View provides a clean, user-friendly interface for your Food Ordering System, ensuring that customers can update their credentials with confidence and ease.
Step-by-Step Code Explanation
@model ChangePasswordViewModel: This line links our HTML form to the validation logic we created in the ViewModel. It allows the page to "know" about rules like minimum length and matching passwords.Card Layout: We use
justify-content-centerandcol-md-6to center the form on the screen. The bg-warning header color is used to catch the user's eye, signifying a high-priority account change.Dynamic Notifications: The
TempData["Success"]check automatically displays a green success alert once the password is changed, providing clear feedback.Tag Helpers: We use
asp-forfor every input. This is a powerful ASP.NET Core feature that automatically generates the correctid,name, and validation attributes in the final HTML.Validation Spans: The
<span asp-validation-for="...">tags are placeholders for error messages. If a user enters a weak password or fails the "confirm password" match, the error message will appear right under the text box in red.Navigation Links: A "Back to Profile" button is included to ensure smooth navigation (UX), allowing users to return to their dashboard without using the browser's back button.
@model FoodOrderingSystem.Models.ViewModels.ChangePasswordViewModel
@{
ViewData["Title"] = "Change Password";
}
<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-warning text-dark">
<h5 class="mb-0"><i class="bi bi-key"></i> Change Password</h5>
</div>
<div class="card-body">
@if (TempData["Success"] != null)
{
<div class="alert alert-success">@TempData["Success"]</div>
}
<form asp-action="ChangePassword" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="mb-3">
<label asp-for="CurrentPassword" class="form-label"></label>
<input asp-for="CurrentPassword" class="form-control" />
<span asp-validation-for="CurrentPassword" class="text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="NewPassword" class="form-label"></label>
<input asp-for="NewPassword" class="form-control" />
<span asp-validation-for="NewPassword" class="text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="ConfirmPassword" class="form-label"></label>
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
<div class="d-flex justify-content-between">
<a href="/Account/Profile" class="btn btn-secondary">Back to Profile</a>
<button type="submit" class="btn btn-warning">Change Password</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
We are completing the security cycle with the ChangePassword POST Action. This method is the "Brain" of the operation—it validates the user's intent, verifies their current identity, and securely updates their credentials in the database.
Step-by-Step Code Explanation
Identity Verification: We retrieve the
UserIdfrom the session. This ensures that the person attempting to change the password is the actual owner of the account.ModelState.IsValid: This checks if the user's input matches our ChangePasswordViewModel rules (like the minimum length of 6 characters and the "Confirm Password" match).Current Password Check: This is a vital security layer. The line
user.Password != model.CurrentPasswordchecks if the user truly knows their existing password. if they fail this, we add a specific error to theCurrentPasswordfield and keep them on the page.Database Update: Once verified, we assign
user.Password = model.NewPassword.Data Persistence:
_context.SaveChanges()sends the update command to your SQL database.Success Feedback: We use
TempData["Success"]to carry a "Password changed successfully!" message back to the Profile page after the redirect.
[HttpPost]
public IActionResult ChangePassword(ChangePasswordViewModel model)
{
var userId = HttpContext.Session.GetInt32("UserId");
if (userId == null) return RedirectToAction("Login");
if (ModelState.IsValid)
{
var user = _context.Users.Find(userId);
if (user.Password != model.CurrentPassword) // In production, verify hash!
{
ModelState.AddModelError("CurrentPassword", "Current password is incorrect.");
return View(model);
}
user.Password = model.NewPassword; // In production, hash the password!
_context.SaveChanges();
TempData["Success"] = "Password changed successfully!";
return RedirectToAction("Profile");
}
return View(model);
}
We are focusing on the navigation and accessibility of our security features. This List Group snippet is a key UI element that we place on the Profile Dashboard. It provides the user with a centralized "Command Center" to manage their orders and account security without searching through complex menus.
Step-by-Step Code Explanation
list-group shadow: We use Bootstrap's list group component to create a clean, stacked menu. Theshadowclass adds a modern depth to the container, making it pop against the background of your Food Ordering System.Navigation Links (
<a>tags): These are the "action" items.The first link points to
/Order/MyOrders, connecting the user to their purchase history.The second link points to
/Account/ChangePassword, which triggers the GET method we created to show the password update form.
list-group-item-action: This specific Bootstrap class makes the links interactive. When a user hovers over "Change Password," the background color changes slightly, signaling that the item is clickable.Bootstrap Icons (
bi):bi-bag-check: A shopping bag icon for orders.bi-key: A key icon for security, instantly telling the user that this link leads to password management.
me-2: This utility class adds a small "margin-end" to the icon, creating perfect spacing between the symbol and the text.
<div class="card shadow mb-4">
....
</div>
<div class="list-group shadow">
<a href="/Account/ChangePassword" class="list-group-item list-group-item-action">
<i class="bi bi-key me-2"></i> Change Password
</a>
</div>

Comments
Post a Comment