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
  1. User types "johndoe" in the Username field and tabs away.
  2. jQuery unobtrusive intercepts the blur event and halts standard validation.
  3. An AJAX call is made to /Account/VerifyUsername?username=johndoe.
  4. The server queries the DB and returns JSON: true (valid) or "Username taken!" (invalid).
  5. 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. Returning Ok() or null will 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."

Questions on this lesson 0

Sign in to ask a question or upvote helpful answers.

No questions yet — be the first to ask!

ASP.NET Core MVC Mastery
Course syllabus
1. Core Framework
MODULE 1: INTRODUCTION & ENVIRONMENT SETUP
2. View Engine
MODULE 2: .NET CORE FUNDAMENTALS
MODULE 3: ASP.NET CORE BASICS
MODULE 4: MVC FUNDAMENTALS
MODULE 5: DATA PASSING TECHNIQUES
MODULE 6: ROUTING
MODULE 7: VIEWS & UI
MODULE 8: ACTION RESULTS
MODULE 9: HTML HELPERS
MODULE 10: TAG HELPERS
MODULE 11: MODEL BINDING
MODULE 12: VALIDATION
MODULE 13: STATE MANAGEMENT
MODULE 14: FILTERS & SECURITY
MODULE 15: ENTITY FRAMEWORK CORE (DEEP DIVE)
MODULE 16: DESIGN PATTERNS
MODULE 17: FILE HANDLING
MODULE 18: ADVANCED ASP.NET CORE
MODULE 19: PERFORMANCE & BEST PRACTICES
MODULE 20: RAZOR PAGES (BONUS)
MODULE 21: REAL-WORLD PROJECTS (🔥 MUST DO)
Toolliyo Assistant
Ask about tutorials, ebooks, training, pricing, mentor services, and support. I use public site content only—not admin or internal tools.

care@toolliyo.com

Need callback? Share your details