Data Entry
In the first part of this chapter, you’ll learn about model binding, which is a powerful MVC
Framework feature for handling data entry using conventions rather than writing lots of code.
After that, you’ll see how to apply your knowledge of controllers, views, model binding, and
MVC architecture with recipes for the following:
• Enforcing validation and business rules
• Maintaining UI state across multiple requests
• Creating a multistep form (also known as a wizard)
• Blocking spam using a custom CAPTCHA widget
• Preventing data tampering (tamper窜改) using HMAC codes
These recipes are of course just starting points—you can customize them however you wish.
Model-Binding to Action Method Parameters
You’ve already been using the framework’s model binding feature—every time your action
methods have taken parameters—for example,
public ActionResult RegisterMember(string email, DateTime dateOfBirth)
{
// ...
}
To execute this action method, the MVC Framework’s built-in ControllerActionInvoker
uses components called DefaultModelBinder and ValueProviderDictionary (unless you’ve
replaced them with custom implementations of their respective interfaces) to convert incoming
request data into a suitable .NET object for each action method parameter. Over the next
few pages, you’ll learn what these components do and how they work.
Table 11-1. Where Model Binding, by Default, Gets Its Raw Incoming Data (in Priority Order)
Location Interpretation
Form (i.e., POST parameters) Culture sensitive (CultureInfo.CurrentCulture)
RouteData (i.e., curly brace routing Culture insensitive (CultureInfo.InvariantCulture)
parameters plus defaults)
QueryString Culture insensitive (CultureInfo.InvariantCulture)
So, the previous example’s email parameter would be populated from
1. Request.Form["email"], if it exists
2. Otherwise, RouteData.Values["email"], if it exists
3. Otherwise, Request.QueryString["email"], if it exists
4. Otherwise, null
public ActionResult RegisterMember([Bind(Prefix = "newuser")] Person myperson)
{
// ...
}
public ActionResult RegisterMember([Bind(Include = "Name, Email")] Person myperson)
{
// ...
}
Or you can specify a list of properties to exclude from binding:
public ActionResult RegisterMember([Bind(Exclude = "DateOfBirth")] Person myperson)
{
// ...
}
Second, you can apply a [Bind] attribute to the target type itself. This rule will then apply
globally, across all your action methods, whenever that type is model bound—for example,
[Bind(Include = "Email, DateOfBirth")]
public class Person
{
public string Name { get; set; }
public string Email { get; set; }
public DateTime DateOfBirth { get; set; }
}
文件上传:
For example, to let the user upload a file, add to one of your views a <form> like this:
<form action="<%= Url.Action("UploadPhoto") %>"
method="post"
enctype="multipart/form-data">
Upload a photo: <input type="file" name="photo" />
<input type="submit" />
</form>
You can then retrieve and work with the uploaded file in the action method:
public ActionResult UploadPhoto(HttpPostedFileBase photo)
{
// Save the file to disk on the server
string filename = // ... pick a filename
photo.SaveAs(filename);
// .. or work with the data directly
byte[] uploadedBytes = new byte[photo.ContentLength];
photo.InputStream.Read(uploadedBytes, 0, photo.ContentLength);
// now do something with uploadedBytes
}