"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.
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.
/Account/VerifyUsername?username=johndoe.true (valid) or "Username taken!" (invalid).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);
}
}
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; }
}
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" />
}
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);
}
HttpMethod = "POST" for remote actions to prevent GET caching and keep data out of server logs.Json(true) on success. Returning Ok() or null will fail client-side unobtrusive parsing._ValidationScriptsPartial. Without it, the browser submits the form normally, bypassing AJAX.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."