Tutorials ASP.NET Core MVC Mastery
Remote Validation
On this page
Remote Validation in ASP.NET Core MVC — Server-Side Validation via AJAX
"Is this username taken?" "Does this discount code exist?" Traditional validation requires a full page submission, ruining the user experience. Remote Validation bridges the gap, allowing your client-side form to asynchronously call a server-side action to validate a field before the user clicks submit.
1. WHAT is Remote Validation?
Remote validation in ASP.NET Core utilizes the [Remote] data annotation attribute. When applied to a model property, the framework generates special HTML5 data-val-remote-* attributes. The client-side jquery.validate.unobtrusive library detects these attributes and automatically fires an AJAX GET/POST request to your specified controller action as the user types or leaves the field.
The Architecture Flow
- User types "johndoe" in the Username field and tabs away.
- jQuery unobtrusive intercepts the blur event and halts standard validation.
- An AJAX call is made to
/Account/VerifyUsername?username=johndoe. - The server queries the DB and returns JSON:
true(valid) or"Username taken!"(invalid). - jQuery unobtrusive displays the error message dynamically.
2. REAL-TIME PRODUCTION EXAMPLE
Step 1: The Server-Side Controller Action
The action must accept a parameter with the exact name of the model property being validated. It must return a JSON boolean (true) if valid, or a JSON string (the error message) if invalid.
public class AccountController : Controller
{
private readonly IUserRepository _userRepo;
public AccountController(IUserRepository userRepo) => _userRepo = userRepo;
// Must be HTTP GET by default, though POST can be configured
[AcceptVerbs("GET", "POST")]
public async Task<IActionResult> IsEmailAvailable(string Email)
{
var emailExists = await _userRepo.EmailExistsAsync(Email);
if (emailExists)
{
// Invalid: Return the error message string
return Json($"The email '{Email}' is already registered.");
}
// Valid: Return boolean true
return Json(true);
}
}
Step 2: The View Model
public class RegisterViewModel
{
[Required]
[EmailAddress]
// ActionName, ControllerName, ErrorMessage (optional)
[Remote(action: "IsEmailAvailable", controller: "Account")]
public string Email { get; set; }
[Required]
[StringLength(100, MinimumLength = 6)]
public string Password { get; set; }
}
Step 3: The Razor View
For remote validation to work, you must include the jQuery validation scripts.
@model RegisterViewModel
<form asp-action="Register" method="post">
<div class="mb-3">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
<!-- Validation message updates live via AJAX -->
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="Password"></label>
<input asp-for="Password" class="form-control" type="password" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
@section Scripts {
<!-- CRITICAL: These scripts are required for [Remote] to function -->
<partial name="_ValidationScriptsPartial" />
}
3. Advanced Validations: AdditionalFields
What if validating a field requires data from another field? For example, checking if a promo code is valid requires knowing the total cart sequence, or verifying an old password requires the user's ID.
public class UpdateProfileViewModel
{
public int UserId { get; set; }
// Send the UserId field ALONG with the Email field to the server
[Remote(
action: "VerifyEmailUpdate",
controller: "Profile",
AdditionalFields = nameof(UserId),
HttpMethod = "POST")] // Use POST for sensitive lookups
public string Email { get; set; }
}
// The Controller Action now accepts BOTH parameters naturally
[HttpPost]
public async Task<IActionResult> VerifyEmailUpdate(string Email, int UserId)
{
// Check if the email belongs to someone ELSE
var existingUser = await _userRepo.FindByEmailAsync(Email);
if (existingUser != null && existingUser.Id != UserId)
{
return Json("Email belongs to another user.");
}
return Json(true);
}
4. Best Practices & Pitfalls
✅ DO
- Always double-check validation on the server during the final POST. Hackers can disable JavaScript or bypass AJAX.
- Use
HttpMethod = "POST"for remote actions to prevent GET caching and keep data out of server logs. - Ensure actions return
Json(true)on success. ReturningOk()ornullwill fail client-side unobtrusive parsing.
❌ DON'T
- Don't do heavy processing in Remote actions. They fire on every blur/keyup.
- Don't forget
_ValidationScriptsPartial. Without it, the browser submits the form normally, bypassing AJAX. - Avoid Remote validation in Web APIs. This is strictly a UI pattern relying on jQuery unobtrusive validation.
5. Interview Mastery
Q: "If a property has a [Remote] validation attribute, do you still need to perform that validation logic in your main HttpPost Create/Update action?"
Architect Answer: "Absolutely yes. Remote validation is purely a UI/UX enhancement powered by client-side JavaScript. A malicious actor can easily intercept the HTTP request, disable JavaScript via browser DevTools, or submit an API POST directly via Postman, bypassing the Remote check entirely. Never trust client-side validation; always re-verify invariants (like username uniqueness or stock availability) inside the final transactional POST action before saving to the database."