One of the biggest areas of feature investment with the
ASP.NET MVC "Preview 5" release was the work around form post
scenarios. I did an in-depth blog post about these form post scenario features
last month.
Today's beta includes a number of additional tweaks,
enhancements, and refinements in this area. These include:
Built-in Model Binder support for Complex Types
Preview 5 introduced the concept of "model
binders" - which allow you to map incoming form post values to complex
.NET types passed as Controller action method parameters. Model binders
in preview 5 were extensible, and you could create custom binders and register
them at multiple levels of the system. Preview 5 didn't ship with any
"pre-built" binders, though, that you could use out of the box (you
instead had to build your own). Today's beta now includes a built-in,
pre-registered, binder that can be used to automatically handle standard .NET
types - without requiring any additional code or registration.
For example, we can now create a "Person" class
like below with standard properties:
Figure 9
And then have a Controller action method take it as an
parameter argument simply by writing the code below:
Figure 10
Because the argument parameter above is named
"person", the model binder will by default look for form-post values
whose key names are in the format "person.Name",
"person.Age", "person.Email". It will then use these
values to create and populate a new "Person" object that is passed
into our action method.
Developers can optionally override the default name mapping
logic using a new [Bind] attribute introduced with today's beta - and by
setting its "Prefix" property. For example, if we set the
prefix property to "PersonToSave", the binder would instead look for
the following form values: "PersonToSave.Name",
"PersonToSave.Age", and "PersonToSave.Email" when creating
the person instance. You can set the prefix to an empty string to have
the binder map "Name", "Age" and "Email" with no
prefix:
Figure 11
The [Bind] attribute allows you to optionally specify an
"Included" or "Excluded" property - which can be used to
either "whitelist" or "blacklist" properties from being
mapped on the objects. For example, the code below indicates that we want
to map only the "Name" and "Age" properties on our person
object:
Figure 12
Important safety tip: In general you want to
be very careful to make sure you don't allow properties to be mapped that you
don't want mapped. Always use include/exclude anytime you have properties
that you don't want to be mapped on an object. For example: assuming there
was a "Salary" property on our Person object - we would not want to
map it unless we explicitly wanted an end-user to be able to set it. You
want to be explicit about not mapping unwanted properties like this to prevent
a hacker from trying to fake out a form request and attempting to submit
additional property information not editable in the UI.
Refactored Model Binder
Infrastructure
The model binder system has been refactored
significantly for the beta. You can now re-use and plug-in functionality
in a much more granular fashion when building your own custom model binders.
Model binders are also now used by the
UpdateModel and TryUpdateModel methods - allowing you to write one binder and
re-use it everywhere any form value is handled inside ASP.NET MVC.