What is the best way to prevent MVC 4 over-posting?
According to MS sources, the [Bind] attribute is supposed to be the easiest way to prevent over-posting by preventing incoming form values from making it to the database. With the latest version of MVC & EF this does not seem to be working as expected/advertised, unless I'm missing something major.
From Wrox Professional ASP.NET MVC 4 (Jon Galloway's Chapter 7), the following class should prevent over-posting:
[Bind(Exclude="IsAdmin")]
public class User
{
public int ID { get; set; }
public string FirstName { get; set; }
public bool IsAdmin { get; set; }
}
But all the [Bind] attribute does is prevent the form submission values from binding to the model. The model then has a blank/default value, which is written back to the database. In this case, it would ensure that IsAdmin = false EVERY TIME you call .SaveChanges() using this model. Any "true" values are overwritten. That's a HUGE security failure.
The alternate syntax - placing [Bind] in the Edit controller action parameter - does the exact same thing:
public ActionResult Edit([Bind(Exclude = "IsAdmin")] User user)
All "true" values are overwritten when .SaveChanges() is called, contradicting K. Scott Allen's blog post on the topic: http://odetocode.com/blogs/scott/archive/2012/03/11/complete-guide-to-mass-assignment-in-asp-net-mvc.aspx
The only alternative seems to be a flurry of dedicated ViewModels all wired up with Automapper. While secure, that seems like a MASSIVE headache, especially as:
- You may have different requirements for Create, Edit, Index, and Detail actions, requiring different ViewModels
- You may need to expose some read-only fields (such as CreatedBy on the Edit action) that cannot have the [ReadOnly] attribute on the property because they are updated by the Create action
I know that somebody is going to respond by saying you should never bind data models to views, but that is the default template behavior and the way it's shown in nearly all documentation. And besides, MVC + EF was supposed to make life easier, not harder, and an ocean of ModelView classes wired up with AutoMapper is not what I consider easier.
So does anybody know how to make [Bind] function as advertised?