Performing Simple Validation (VB)
The goal of this tutorial is to explain
how you can perform validation within an ASP.NET MVC application. For
example, you learn how to prevent someone from submitting a form that
does not contain a value for a required field. You learn how to use
model state and the validation HTML helpers.
Understanding Model
State
You use model state – or more accurately,
the model state dictionary – to represent validation errors. For example,
the Create() action in Listing 1 validates the properties of a Product
class before adding the Product class to a database.
I’m not recommending that you add
your validation or database logic to a controller. A controller should
contain only logic related to application flow control. We are taking
a shortcut to keep things simple.
Listing 1
– Controllers\ProductController.vb
'
' POST: /Product/Create
<AcceptVerbs(HttpVerbs.Post)> _
Public Function Create(<Bind(Exclude:="Id")> ByVal productToCreate As Product) As ActionResult
' Validation logic
If productToCreate.Name.Trim().Length = 0 Then
ModelState.AddModelError("Name", "Name is required.")
End If
If productToCreate.Description.Trim().Length = 0 Then
ModelState.AddModelError("Description", "Description is required.")
End If
If productToCreate.UnitsInStock < 0 Then
ModelState.AddModelError("UnitsInStock", "Units in stock cannot be less than zero.")
End If
If (Not ModelState.IsValid) Then
Return View()
End If
' Database logic
Try
_entities.AddToProductSet(productToCreate)
_entities.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
In Listing 1, the Name, Description,
and UnitsInStock properties of the Product class are validated. If any
of these properties fail a validation test then an error is added to
the model state dictionary (represented by the ModelState property of
the Controller class).
If there are any errors in model state
then the ModelState.IsValid property returns false. In that case, the
HTML form for creating a new product is redisplayed. Otherwise, if there
are no validation errors, the new Product is added to the database.
Using the Validation
Helpers
The ASP.NET MVC framework includes
two validation helpers: the Html.ValidationMessage() helper and the
Html.ValidationSummary() helper. You use these two helpers in a view
to display validation error messages.
The Html.ValidationMessage() and Html.ValidationSummary()
helpers are used in the Create and Edit views that are generated automatically
by the ASP.NET MVC scaffolding. Follow these steps to generate the Create
view:
- Right-click the Create()
action in the Product controller and select the menu option Add View
(see Figure 1).
- In the Add View dialog,
check the checkbox labeled Create a strongly-typed view
(see Figure 2).
- From the View data class
dropdown list, select the Product class.
- From the View content
dropdown list, select Create.
- Click the Add button.
Make sure that you build your application
before adding a view. Otherwise, the list of classes won’t appear
in the View data class dropdown list.
After you complete these steps, you
get the Create view in Listing 2.
Listing 2
– Views\Product\Create.aspx
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of MvcApplication1.Product)" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Create</title>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Create</h2>
<%= Html.ValidationSummary() %>
<% Using Html.BeginForm()%>
<fieldset>
<legend>Fields</legend>
<p>
<label for="Name">Name:</label>
<%= Html.TextBox("Name") %>
<%= Html.ValidationMessage("Name", "*") %>
</p>
<p>
<label for="Description">Description:</label>
<%= Html.TextBox("Description") %>
<%= Html.ValidationMessage("Description", "*") %>
</p>
<p>
<label for="Price">Price:</label>
<%= Html.TextBox("Price") %>
<%= Html.ValidationMessage("Price", "*") %>
</p>
<p>
<label for="UnitsInStock">UnitsInStock:</label>
<%= Html.TextBox("UnitsInStock") %>
<%= Html.ValidationMessage("UnitsInStock", "*") %>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% End Using %>
<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
In Listing 2, the Html.ValidationSummary()
helper is called immediately above the HTML form. This helper is used
to display a list of validation error messages. The Html.ValidationSummary()
helper renders the errors in a bulleted list.
The Html.ValidationMessage() helper
is called next to each of the HTML form fields. This helper is used
to display an error message right next to a form field. In the case
of Listing 2, the Html.ValidationMessage() helper displays an asterisk
when there is an error.
The page in Figure 3 illustrates the
error messages rendered by the validation helpers when the form is submitted
with missing fields and invalid values.
Notice that the appearance of the HTML
input fields are also modified when there is a validation error. The
Html.TextBox() helper renders a class="input-validation-error"
attribute when there is a validation error associated with the property
rendered by the Html.TextBox() helper.
There are three cascading style sheet
classes used to control the appearance of validation errors:
- input-validation-error –
Applied to the <input> tag rendered by Html.TextBox() helper.
- field-validation-error –
Applied to the <span> tag rendered by the Html.ValidationMessage()
helper.
- validation-summary-errors
– Applied to the <ul> tag rendered by the Html.ValidationSumamry()
helper.
You can modify these cascading style
sheet classes, and therefore modify the appearance of the validation
errors, by modifying the Site.css file located in the Content folder.
The HtmlHelper class includes read-only
static properties for retrieving the names of the validation related
CSS classes. These static properties are named ValidationInputCssClassName,
ValidationFieldCssClassName, and ValidationSummaryCssClassName.
Prebinding Validation
and Postbinding Validation
If you submit the HTML form for creating
a Product, and you enter an invalid value for the price field and no
value for the UnitsInStock field, then you’ll get the validation messages
displayed in Figure 4. Where do these validation error messages come
from?
There are actually two types of validation
error messages – those generated before the HTML form fields are bound
to a class and those generated after the form fields are bound to the
class. In other words, there are prebinding validation errors and postbinding
validation errors.
The Create() action exposed by the
Product controller in Listing 1 accepts an instance of the Product class.
The signature of the Create method looks like this:
Public Function Create(<Bind(Exclude:="Id")> ByVal productToCreate As Product) As ActionResult
The values of the HTML form fields
from the Create form are bound to the productToCreate class by something
called a model binder. The default model binder adds an error message
to model state automatically when it cannot bind a form field to a form
property.
The default model binder cannot bind
the string “apple” to the Price property of the Product class. You
can’t assign a string to a decimal property. Therefore, the model
binder adds an error to model state.
The default model binder also cannot
assign the value Nothing to a property that does not accept the value
Nothing. In particular, the model binder cannot assign the value Nothing
to the UnitsInStock property. Once again, the model binder gives up
and adds an error message to model state.
If you want to customize the appearance
of these prebinding error messages then you need to create resource
strings for these messages.
Summary
The goal of this tutorial was to describe
the basic mechanics of validation in the ASP.NET MVC framework. You
learned how to use model state and the validation HTML helpers. We also
discussed the distinction between prebinding and postbinding validation.
In other tutorials, we’ll discuss various strategies for moving your
validation code out of your controllers and into your model classes.