Create Quick Database Interfaces with ASP.NET Dynamic Data

Customizing using attributes

So far, you have briefly seen how ASP.NET Dynamic Data
applications work. After you have seen how the different
features of the application, you should next learn how you
can control how data is displayed in the application.

Earlier, when looking at the Global.asax.cs
file, the ScaffoldAllTables property was set to
true. This property value means that every table in the
model became active in the application for editing and
deleting. But maybe you would like to better control which
tables are active. To do this, you need to use
attributes. In the data model, the classes that represent
the tables are defined as partial classes. This means that
you can effectively continue adding features to these
classes, including specifying attributes. To write the
necessary code, you need to add a new file to your
project.

The easiest way to add this file is to right-click your
project in Visual Studio's Solution Explorer and then choose
the Add/Class command. Visual Studio will then ask you for a
class name; choose any name you want, for instance
"MetadataControl". Once the file has been created, you can
start editing it.

Assuming for example, that you want to hide the employees
table, you would add a partial class definition for the
Employee class, originally defined in the ADO.NET entity
model file NorthwindModel.Designer.cs (if you followed the
naming convention suggested earlier). Replacing the skeleton
public class definition written by Visual Studio, add the
following code:

With this definition, the Employees class defined in the
original entity model gets extended, and the ScaffoldTable
attribute is added. This attribute is one of the key ones in
ASP.NET Dynamic Data. Many of the most important attributes
are defined in the System.ComponentModel.DataAnnotations
namespace. Other often-needed attributes include
ScaffoldColumn (of which you will soon see an example),
DisplayName, DisplayFormat, Range and
UIHint.

With the above ScaffoldTable attribute (and the value of
false) in place, you should now run the application to see
how it behaves. In the initial screen showing the names of
tables in the data model, you should see that the Employees
table link is missing. And, if you take a look for example
at the Orders table, you can see that the hyperlinks to the
table are also gone.

Notice how there are two ways to show and hide tables.
You can make all tables visible using the
ScaffoldAllTables property in the
Global.asax.cs file, and then hide them one by
one using attributes. The other option is to go the other
way around: leave ScaffoldAllTables to false,
and then allow individual tables to become visible using the
ScaffoldTable(true) attribute.

Next, let's see how you can control individual fields
using attributes. Previously, you used partial classes to
help in specifying the ScaffoldTable attribute, but if you
wanted to have attributes associated with individual
columns, you would need another kind of solution. Since you
cannot have partial property definitions, you must use an
additional class to define properties that are associated
with database fields.

To do this, you start with a similar partial class like
with the ScaffoldTable attribute, but you use the
MetadataType attribute to associate another class with the
original. Then, this additional class, called the metadata
class, allows you to define public properties for each field
in the data model which you want to control. The following
example shows how this is done:

Here, the partial class Employees is defined as before,
but also the MetadataType attribute is applied
to the class. The constructor of this attribute accepts a
type as a parameter, which in turn points to the metadata
class called EmployeesMetadata. This class is
then free to define new properties and associated field-
level attributes to them. For instance, here the
DisplayName attribute (in the
System.ComponentModel namespace) is associated
with the column Title to specify a new, more descriptive
title for the field. Of course, the property names must
match those in the database for this to work.

Modifying user interfaces

While understanding how attributes are applied in ASP.NET
Dynamic Data applications is key to your success, you must
also understand how you can customize the web page
templates that together create the user interface for your
application. As briefly mentioned before, ASP.NET Dynamic
Data applications by default utilize an ASP.NET template
file. This file is named Site.master, and can be found from
the root folder of the project.

If you wanted to change the user interface, then editing
the Site.master file would be a good place to start. It
utilizes XHTML code and defines a single content placeholder
into which the actual pages are embedded at runtime.
Furthermore, the master file uses CSS styles, which are in
turn defined in the file Site.css. To do application-wide
font and color changes, editing this style sheet file would
give you a head start.

In addition to the template and style sheet files, you do
of course have the actual .aspx pages that implement the
four basic operations. This can be found inside the
DynamicData\PageTemplates folder in your solution. For
instance, you might wish to change how the listing pages
operate. For this need, you would edit List.aspx.

Another option for customizations is the
DynamicData\FieldTemplates folder. This folder contains the
user controls that ASP.NET Dynamic Data uses to render
different database field types. For instance, a Boolean
field is shown as a checkbox to the user. If you wanted to
change this, you could simply go and edit the files
Boolean.ascx and Boolean_Edit.ascx. There usually are two
controls defined for each data type: one for viewing and
another for editing. Often, the viewer control is simply a
read-only version of the edit control.

It is also possible to define your own user controls to
work with your data. For instance, you might wish to change
the control that is used to display dates. By default, the
DateTime.ascx control uses a textbox control for this, but
you could easily change this to, say, a calendar control. If
you wanted to make this an application-wide change, then you
could simply edit DateTime.ascx, and all date fields would
change. You can also change the control on a field by field
basis. This is done using attributes, just like with the
previously shown ScaffoldTable and ScaffoldColumn
attributes. Assume that you had implemented a calendar user
control DataTimeCalendar.ascx like this:

This declaration mirrors any other user control
definition. However, for a user control to be suitable for
ASP.NET Dynamic Data use, you need to tweak the code-behind
file a bit. First, you need to change the inheritance
chain from the regular
System.Web.UI.UserControl to
System.Web.DynamicData.FieldTemplateUserControl.

Of course, you are not limited to controls that are
available in ASP.NET. For instance if you have purchased a
nice, feature-rich third-party control or created one on
your own, you are free to use them in your ASP.NET Dynamic
Data applications. Specifying which user control should be
used when ASP.NET Dynamic Data renders the database views
can be controlled using the UIHint attribute. This attribute
is applied to metadata classes just like the ScaffoldColumn
attribute. With the previous DateTimeCalendar user control
declaration in place, you could use the UIHint attribute as
follows:

Here, the HireDate field of the Employees table is
assigned the UIHint attribute with the value of
"DateTimeCalendar". When ASP.NET Dynamic Data shows the
table, the regular text label is replaced with the calendar
control (Figure 7). Note that you also need to write a
couple of lines of code to the user control's code behind
file so that you can set the calendar to show the correct
hire date: