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.IsValidvalidates values but does not prevent over-posting.[ValidateAntiForgeryToken]prevents CSRF but does not prevent mass assignment.