← Back to Articles         
Prevent Over-Posting in MVC

Prevent Over-Posting in MVC

Published on 27 Sep 2026     2 min read ASP.NET Core MVC
MVC

Preventing Over-Posting or Mass-Assignment

Over-posting occurs when a user submits additional fields that they should not be allowed to modify.

Example Attack

Suppose the database entity contains:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public bool IsAdmin { get; set; }
}

A malicious user could submit:

Name=Syed&IsAdmin=true

If the controller binds the entity directly, IsAdmin may be changed.

Recommended Solution: Use a ViewModel

Expose only permitted fields:

public class EditUserViewModel
{
    public string Name { get; set; } = string.Empty;
}

Controller

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(
    int id,
    EditUserViewModel model)
{
    if (!ModelState.IsValid)
        return View(model);

    var user = await _context.Users.FindAsync(id);

    if (user is null)
        return NotFound();

    // Update only permitted fields
    user.Name = model.Name;

    await _context.SaveChangesAsync();

    return RedirectToAction("Index");
}

The user cannot bind IsAdmin because it does not exist in the ViewModel.

Other Protection Options

Method Usage
ViewModel/DTO Recommended; exposes only permitted fields
Explicit mapping Updates only approved entity properties
[Bind] Includes only specified properties
[BindNever] Prevents a property from model binding
TryUpdateModelAsync() Updates only explicitly selected properties
Authorization checks Verifies the current user can perform the update
Anti-forgery token Protects MVC forms against CSRF—not over-posting itself

[Bind] Example

public IActionResult Edit(
    [Bind("Id,Name")] User user)

This works, but a dedicated ViewModel is easier and safer to maintain.

TryUpdateModelAsync() Example

await TryUpdateModelAsync(
    user,
    prefix: "",
    u => u.Name);

Library Information

  • Model binding, [Bind], [BindNever], TryUpdateModelAsync() and anti-forgery protection are built into ASP.NET Core MVC.
  • No external NuGet package is required.
  • Mapping libraries such as AutoMapper are optional; manual mapping is safer and clearer for security-sensitive updates.

Key Points

  • Never bind posted form data directly to database entities.
  • Use separate ViewModels for create and edit operations.
  • Load the existing entity from the database.
  • Update only explicitly permitted properties.
  • Perform server-side authorization checks.
  • ModelState.IsValid validates values but does not prevent over-posting.
  • [ValidateAntiForgeryToken] prevents CSRF but does not prevent mass assignment.

 

← Back to Articles