parameter if it detects that its attached property has an error associated with it.
You can call a partial view directly from an action using the normal View
method. If you do this, only the HTML rendered by the partial view will be
included in the HTTP response. This can be very useful if you are returning
data to jQuery.
custom View templates
When you use the Add View dialog to add items to your project, Visual Studio 2010 is actually
executing a T4 template, which determines the code that will be generated. The View Content
drop - down determines which template will be run. If you want to edit them you can fi nd them
in the C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates\
language\Web\MVC\v2\CodeTemplates\AddView folder where language is either “ CSharp ”
or “ VisualBasic. ”
advanced MVC . 463
464 .
chaPter 21 ASp.neT mVc
Editing these files directly will make the change across all MVC projects on the local machine, but
you cannot use this technique to create project-specific templates. It is also very hard to version
control these files effectively with the rest of your application. You can get around both of these
issues by creating a CodeTemplates\AddView folder under the root of your project and copying the
T4 templates into it as shown in Figure 21-11 When the Add View dialog is populating the View
Content drop-down list it will use these templates instead of the global ones.
Additionally, you can create your own templates by adding T4 template files into this folder. Figure 21-11
shows the template file MyViewTemplate.tt and Figure 21-12 shows “MyViewTemplate” showing up in
the drop-down list.
fiGure 21-11 fiGure 21-12
Custom templates can be host specific and the Host is of type MvcTextTemplateHost, which
contains all of the properties defined by the Add View dialog. See Chapter 14, “Code Generation
with T4,” for more information about creating T4 templates.
dynamic data templates
Dynamic Data is a feature of ASP.NET Web Forms that allows you to render UI based on metadata
associated with the model. Although ASP.NET MVC does not integrate directly with Dynamic
Data, a number of new features in ASP.NET MVC 2.0 are similar in spirit. Templates in ASP.NET
MVC 2.0 are able to render parts of your model in different ways, whether they are small and
simple such as a single string property or large and complex like the whole product class. The
templates are exposed by Html helper methods. There are templates for display and templates for
editing purposes.
advanced MVC .
465
Display Templates
The Details view that is created by the Add View dialog contains code to render each property. Here
is the markup for just two of these properties:
c#
<p>
ProductID:
<%= Html.Encode(Model.ProductID) %>
</p>
<p>
Name:
<%= Html.Encode(Model.Name) %>
</p>
Vb
<p>
ProductID:
<%= Html.Encode(Model.ProductID) %>
</p>
<p>
Name:
<%= Html.Encode(Model.Name) %>
</p>
With the new templates feature you can change this to the following:
c#
<p>
<%= Html.LabelFor(x => x.ProductID) %>
<%= Html.DisplayFor(x => x.ProductID) %>
</p>
<p>
<%= Html.LabelFor(x => x.Name) %>
<%= Html.DisplayFor(x => x.Name) %>
</p>
Vb
<p>
<%: Html.LabelFor(Function(x As ProductsMVC.Product) x.ProductID)%>
<%: Html.DisplayFor(Function(x As ProductsMVC.Product) x.ProductID) %>
</p>
<p>
<%: Html.LabelFor(Function(x As ProductsMVC.Product) x.Name)%>
<%: Html.DisplayFor(Function(x As ProductsMVC.Product) x.Name) %>
</p>
This has a number of immediate advantages. First, the label is no longer hard coded into the view.
Because the label is now strongly typed it will be updated if you refactor your model class. In
addition to this you can apply a System.ComponentModel.DisplayName attribute to your model
466 .
chaPter 21 ASp.neT mVc
(or to a model metadata proxy) to change the text that is displayed to the user. This helps to ensure
consistency across the entire application. The following code snippet shows the Product metadata
proxy with a couple of DisplayNameAttributes and Figure 21-13 shows the rendered result:
c#
public class ProductValidationMetadata
{
[DisplayName("ID")]
public int ProductID { get; set; }
[Required, StringLength(256)]
[DisplayName("Product Name")]
public string Name { get; set; }
[Range(0, 100)]
public int DaysToManufacture { get; set; }
}
Vb
Public Class ProductMetaData
<DisplayName("ID")>
Property ProductID As Integer
<Required(), StringLength(256)> _
<DisplayName("Product Name")>
Property Name As String
<Range(0, 100)>
Property DaysToManufacture As Integer
End Class
The DisplayFor helper is also providing a lot of hidden flexibility. It is selecting a template based
on the type of the property that it is displays. You can override each of these type-specific views by
creating a partial view named after the type in the Shared\DisplayTemplates folder. Figure 21-14
shows a String template and Figure 21-15 shows the output result.
fiGure 21-13 fiGure 21-14 fiGure 21-15
c#
< %@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" % >
STRING START
< %= Html.Encode(ViewData.TemplateInfo.FormattedModelValue) % >
STRING END
Vb
< %@ Control Language="VB" Inherits="System.Web.Mvc.ViewUserControl" % >
STRING START
< %= Html.Encode(ViewData.TemplateInfo.FormattedModelValue) % >
STRING END
You can also create controller - specifi c templates by putting them inside a
DisplayTemplates subfolder of the controller - specifi c Views folder.
Although the display template is selected based on the type of the property by default you can
override this by either supplying the name of the template to the DisplayFor helper or applying a
System.ComponentModel.DataAnnotations.UIHintAttribute to the property. This attribute
takes a string that identifi es the type of template to use. When the framework needs to render the
display for the property it tries to fi nd the display template described by the UI Hint. If one is not
found it looks for a type - specifi c template. If a template still hasn ’ t been found, the default behavior
is executed.
If you are simply applying LabelFor and DisplayFor for every property on your model, you can
use the Html.DisplayForModel helper method. This method renders a label and a display template
for each property on the model class. You can prevent a property from being displayed by this helper
by annotating it with a System.ComponentModel.DataAnnotations.ScaffoldColumnAttribute
passing it the value false .
If you want to change the way the DisplayForModel is rendered, you can create
a type - specifi c template for it. If you want to change the way it renders generally,
create an Object display template.
A number of built - in display templates are available that you can use out of the box. Be aware that if
you want to customize the behavior of one of these you will need to re - create it from scratch.
. String: No real surprises, just renders the string contents itself. This template does HTML
encode the property value, though.
. Html: The same as string but without the HTML encoding. This is the rawest form of
display that you can have. Be very careful using this template because it is a vector for
malicious code injection such as Cross Site Scripting Attacks (XSS).
advanced MVC . 467
468
.
chaPter 21 ASp.neT mVc
.
EmailAddress: Renders an e-mail address as a mailto: link.
.
Url: Renders a URL as an HTML anchor.
.
HiddenInput: Does not render the property at all unless the ViewData.ModelMetaData
.HideSurroundingHtml property is false.
.
Decimal: Renders the property to two decimal places.
.
Boolean: Renders a read-only checkbox for non-nullable values and a read-only drop-down
list with True, False, and Not Set options for nullable properties.
.
Object: Renders complex objects and null values.
edit Templates
It probably comes as no surprise that there are corresponding EditorFor and EditorForModel
Html helpers that handle the way properties and objects are rendered for edit purposes. Editor
templates can be overridden by supplying partial views in the EditTemplates folder. Edit templates
are able to use the same UI hint system that display templates use. Just as with display templates,
you can use a number of built-in editor templates out of the box:
.
String: Renders a standard textbox, initially populated with the value if provided and
named after the property. This ensures that it will be used correctly by the model binder to
rebuild the object on the other side.
.
Password: The same as string but renders an HTML PASSWORD input instead of a textbox.
.
MultilineText: Creates a multi-line textbox. There is no way to specify the number of rows
and columns for this textbox here. It is assumed that you will use CSS to do that.
.
HiddenInput: Similar to the display template, renders an HTML HIDDEN
input.
.
Decimal: Similar to the display template but renders a textbox to edit the value.
.
Boolean: If the property type is non-nullable this renders a checkbox control. If this
template is applied to a nullable property it renders a drop-down list containing the same
three items as the display template.
.
Object: Renders complex editors.
Brad Wilson has a good, multi-part, in-depth tutorial on ASP.NET MVC 2.0
Templates on his blog starting at http://bradwilson.typepad.com/
blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html.
jquery
jQuery is an open-source JavaScript framework that is included by default with the ASP.NET MVC
framework. The basic element of jQuery is the function $(). This function can be passed a JavaScript
DOM element or a string describing elements via a CSS selector. The $()
function returns a jQuery
advanced MVC .
469
object that exposes a number of functions that affect the elements contained. Most of these functions
also return the same jQuery object so these function calls can be chained together. As an example,
the following snippet selects all of the H2 tags and adds the word “section” to the end of each one:
Javascript
$("h2").append(" section");
To make use of jQuery you need to create a reference to the jQuery library found in the /Scripts
folder by adding the following to the head section of your page:
htMl
<script type="text/javascript" src="/Scripts/jquery-1.3.2.js"></script>
It is possible to use jQuery to make an HTTP request by using the $.get and $.post methods.
These methods accept a URL and can optionally have a callback function to provide the results to. The
following view renders the time inside two div tags called server and client, respectively. There is also
a button called update, which when clicked makes a GET request to the /time URL. When it receives
the results it updates the value displayed in the client div but not the server one. In addition to this it
uses the slideUp and slideDown functions to animate the client time in the UI.
c#
<%@ Page Language=”C#” Inherits=”System.Web.Mvc.ViewPage<System.String>” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head runat=”server”>
<title>Index</title>
<script type=”text/javascript” src=”/Scripts/jquery-1.3.2.js”></script>
<script type=”text/javascript”>
$(document).ready(function () {
$(‘#updater’).click(UpdateNow);
});
function UpdateNow() {
$.get(‘/time’, function (data) {
$(‘#clientTime’).slideUp(‘fast’, function () {
$(‘#clientTime’).empty().append(data).slideDown();
});
});
}
</script>
</head>
<body>
<div>
<h2>
Server</h2>
<div id=”serverTime”>
<%:Model %></div>
<h2>
Client</h2>
470 .
chaPter 21 ASp.neT mVc
<div id=”clientTime”>
<%:Model %></div>
<input type=”button” value=”Update” id=”updater” />
</div>
</body>
</html>
Code snippet Views\Time\Index.aspx
Here is the action method that controls the previous view. It uses the IsAjaxRequest extension
method to determine if the request has come from jQuery. If it has, it returns just the time as a
string, otherwise it returns the full view.
c#
public ActionResult Index()
{
var now = DateTime.Now.ToLongTimeString();
if (Request.IsAjaxRequest())
return Content(now);
return View(now as object);
}
Code snippet Controllers\Time.cs
Vb
Function Index() As ActionResult
Dim timeNow = Now.ToString()
If Request.IsAjaxRequest() Then
Return Content(timeNow)
End If
Return View(CType(timeNow, Object))
End Function
Code snippet Controllers\Time.vb
jQuery is a rich client-side programming tool with an extremely active community and a large
number of plug-ins. For more information about jQuery including a comprehensive set of tutorials
and demos see http://jquery.com.
suMMary
The ASP.NET MVC framework makes it easy to build highly testable, loosely coupled web
applications that embrace the nature of HTTP. The 2.0 release has a lot of productivity gains
including Templates and Visual Studio integration. For more information about ASP.NET MVC, see