An Introduction to Dynamic Data

Rapidly Create Rich Data-bound Web Sites

From the Source

ASP.NET VERSIONS: 3.5

 

An Introduction to Dynamic Data

Rapidly Create Rich Data-bound Web Sites

 

By Marcin Dobosz and Scott Hunter

 

Creating even a simple data-driven Web site from a default ASP.NET project can be a time-consuming task. One of the new features of the .NET 3.5 SP1 release that aims to address this is a framework called Dynamic Data for rapidly creating rich data-bound Web sites.

 

Getting started with Dynamic Data is as simple as:

  • Creating a new project using the Dynamic Data project template.
  • Generating a data model from a database (both LINQ to SQL and Entity Framework ORM solutions are supported).
  • Registering the model with the Dynamic Data runtime.

 

The result is a fully functional Web site with out-of-the-box support for CRUD operations, foreign-key relationship navigation, automatic validation, and filtering. You can take the default appearance and functionality and selectively replace or modify the site at various levels of granularity, such as changing the look of the entire site or simply modifying how fields from a single column in a single table are displayed. The Dynamic Data framework enables this by using scaffolding, templates, metadata, and convention-based naming. It also includes enhancements to data source controls, as well as to the DetailsView, FormView, GridView, and ListView controls. This article provides an introduction to the new features in Dynamic Data.

 

Scaffolding and Page Templates

A key feature of Dynamic Data is automatic scaffolding of the tables in a data model. Dynamic Data scaffolds a table page by first automatically discovering information about the data from the model. Using this information, it then dynamically modifies a page template, sets up the appropriate columns and filters for data-bound controls, and populates those controls with data from the database. This means that a single page template can be used to generate UI for any number of tables, regardless of what types of data or relationships they contain.

 

To enable scaffolding, you must register the data model with the Dynamic Data runtime in the site s Global.asax file. The following example shows code that you might use to register a LINQ to SQL data context class for the Northwind database:

 

MetaModel model = new MetaModel();

model.MetaModel.RegisterContext(typeof(NorthwindDataContext),

new ContextConfiguration() { ScaffoldAllTables = true });

 

Figure 1 shows the result of running the application. A Dynamic Data project has a starter Web page that displays a list of tables in the data model. When you click a table in the list, you browse to a scaffolded page for that table.

 


Figure 1: Starter page of a Dynamic Data project.

 

Figure 2 shows a scaffolded master/details page for the Products table. The default Dynamic Data master/details page template does the following:

  • Adds filtering drop-down controls for Boolean columns (for the Discontinued field) and foreign-key columns (for the Category and Supplier fields).
  • Displays foreign-key columns (Category and Supplier) using meaningful textual representations (rather than displaying a numeric id value) that are rendered as hyperlinks. Clicking a link navigates to a scaffolded page for the parent table. In edit mode, foreign keys are rendered as drop-down lists that let a user modify the foreign-key value for that record.
  • Turns one-to-many relationship columns (Order_Details) into hyperlinks that navigate to a scaffolded page for that table.
  • Provides a customized GridView pager control.
  • Provides a DetailsView control for displaying the details of a selected record.

 


Figure 2: A sample scaffold page.

 

Page templates are ordinary ASP.NET pages, and editing a page template allows you to globally change the behavior and appearance of all scaffolded pages in the site. In addition to the default master/details page template, Dynamic Data ships with individual list, details, edit, and insert page templates for performing CRUD operations on separate pages. Changing templates or adding new ones requires only a minor configuration change. Additionally, you can implement custom pages for any table to override the scaffolding behavior for that table. The Dynamic Data runtime will automatically discover the existence of a custom page and use it as the page template for the table.

 

Field Templates

Standard ASP.NET data-bound controls such as GridView or DetailsView can automatically generate columns based on the kind of data to which they are bound. However, customizing even a single column (for example, changing display style or adding validators) requires that you create bound or templated columns for each data field. Dynamic Data improves this experience by introducing dynamic field templates.

 

Field templates are reusable user controls that render a single data-bound field. A Dynamic Data-enabled GridView control will choose the appropriate field template based on the field s type. For example, the GridView will use a textbox for string fields and a checkbox for Boolean fields (see Figure 3 for a list of default field templates). You also can specify which field template is used for a field by declaring an override, as you ll see in the metadata section later.

 

Field Template

Data Type

Rendered with

Boolean

Boolean

A CheckBox control.

Children

 

A HyperLink control that navigates to a page that lists the records associated with the row.

DateTime

DateTime

A TextBox control with optional RequiredFieldValidator and DynamicValidator controls in edit mode.

Decimal

Double, Float, Decimal

A TextBox control with optional RequiredFieldValidator, CompareValidator, RangeValidator, and RegularExpressionValidator controls in edit mode.

ForeignKey

 

A HyperLink control that links to the associated entity in display mode, or a DropDownList control in edit mode.

Integer

Int32, Int64, Int16

A TextBox control with optional RequiredFieldValidator, CompareValidator, RangeValidator, and RegularExpressionValidator controls in edit mode.

Text

String

A TextBox control with optional RequiredFieldValidator, RegularExpressionValidator, and DynamicValidator controls in edit mode.

TextArea

String

A TextBox control that is set to multi-line mode, with optional RequiredFieldValidator, RegularExpressionValidator, and DynamicValidator controls in edit mode.

Figure 3: Default Dynamic Data project field templates.

 

When you don t want the control to automatically generate columns, you can declare the set of columns to be displayed by using a new type of data control field called DynamicField. A DynamicField control automatically chooses the correct field template to use. A complement of DynamicField is the DynamicControl control, which can be used in any custom content template, such as inside a TemplateField or inside the FormView or ListView controls.

 

Together, DynamicControl and DynamicField controls reduce a lot of code duplication that is characteristic of data-bound control templates. For example, to customize how date fields are displayed in edit mode, you simply need to modify the DateTime edit template once in an application and the change will be reflected across all Dynamic Data pages.

 

Metadata

A database schema contains a lot of information that can help automatically build a more functional user interface. Dynamic Data automatically extracts model metadata and uses it to drive the behavior of the page templates and the field templates.

 

For example, Dynamic Data uses the following to enhance the UI:

  • Information about associations between tables to display foreign-key columns and use them for navigation between tables.
  • Nullable column information to determine whether a field is required.
  • Data-type information to add validation for a field value.
  • String-length information to restrict the maximum length of text inputs.

 

Dynamic Data supports additional metadata attributes you can declare on the data model to provide information that cannot be automatically detected from the database schema. Figure 4 lists supported metadata attributes. Attributes such as RegularExpression are used by field templates to enable validation controls. You also can create and use custom metadata.

 

Attribute

Description

DataType

Provides a way to declare specific semantic information about a column, independent of storage type. For example, a ZIP code might be stored as either an integer or a string.

Description

Specifies a longer description for a column. The description is presented as a tooltip when a user holds the mouse pointer over the field when editing.

DisplayColumn

Specifies which column to use as the textual representation of a row. The values of that column are used as the labels in elements of a foreign-key drop-down list.

DisplayFormat

Allows you to specify formatting and string-conversion options.

DisplayName

Specifies a friendly display name for a column used in the header text.

MetadataType

Specifies the associated metadata type for an entity type of the data model.

Range

Specifies a minimum and maximum range for values of a column.

RegularExpression

Specifies a regular expression to use as a validation pattern in edit mode.

Required

Specifies that a field must have a value in edit mode.

Scaffold

Specifies whether a table or column should be included in a scaffold page.

StringLength

Specifies the maximum length of a string field.

UIHint

Specifies which template control to use for the UI of a column.

Figure 4: Metadata attributes used by the Dynamic Data runtime.

 

You can annotate the data model using CLR metadata attributes. Both LINQ to SQL and the Entity Framework generate data models using partial classes, which means a class definition can be split across multiple files. This allows you to write the metadata code in a separate file from the generated model, which ensures that your custom code is not overwritten if the model is regenerated.

 

Adding metadata to a model object begins with creating a partial class whose name matches the data-model class to which you want to add metadata. In this partial class, you mark the class by using an attribute that binds a metadata type with the model object class. The skeleton of a partial class with a metadata attribute might look like this:

 

[MetadataType(typeof(ProductMetadata))]

public partial class Product {

}

 

The MetadataType attribute specifies the type (ProductMetadata in this example) that contains metadata for the object (the Product class). The associated metadata type is a class that serves as a proxy for the metadata attributes. Attributes declared on properties of the associated metadata type that match properties of the main type will be treated by the Dynamic Data runtime as if they were declared on the main type itself. Therefore, you can create a metadata class, declare skeleton properties in the metadata class, and mark these properties with attributes. This has the same effect as if you marked the properties of the original data-model class with those attributes.

 

You cannot declare the metadata attributes directly in your partial class (here, the Product class) because the C# and Visual Basic compilers cannot directly apply metadata attributes to class members if the attributes are defined in a partial class in another file. The metadata proxy class solves this limitation.

 

To be recognized by the Dynamic Data runtime, the associated metadata type properties must have public visibility and names that match the names in the main type.

 

The following example of the ProductMetadata class illustrates these metadata attributes for the Products table:

  • The ProductName field is marked with a description attribute that displays a tooltip when users are editing the field.
  • The QuantityPerUnit field is marked as a required field.
  • The UnitsInStock field is marked as having a range between 0 and 100. If the entered value falls outside the specified range, the specified error message is displayed:

 

public class ProductMetadata {

  [Description("Enter the name of the product")]

 public object ProductName { get; set; }

  [Required]

 public object QuantityPerUnit { get; set;}

  [Range(0, 100, ErrorMessage = "Enter a valid value.")]

 public object UnitsInStock { get; set; }

}

 

Model Validation

Metadata attributes such as Range, Required, and RegularExpression provide a way to express simple validation rules. More complex rules can be added to the data model using the extensibility methods that LINQ to SQL and Entity Framework expose.

 

Each field in the data model has a corresponding OnChanging partial method that is called when the field value changes. The Dynamic Data runtime intercepts any validation exceptions that are thrown from these methods, and displays the exception message text next to the associated field. The following example illustrates how to add validation to the ProductName property of the Product class:

 

public partial class Product {

 partial void OnProductNameChanging(string newValue) {

   if (newValue != null && !newvalue.StartsWith("ACME")) {

     throw new ValidationException("Product names must

                                   start with ACME.");

   }

 }

}

 

Figure 5 shows an example of what the Web page will look like when the validation error is raised.

 


Figure 5: Dynamic Data page showing model validation in action.

 

Dynamic Data Folders and Files

A Dynamic Data project in Visual Studio is similar to a regular ASP.NET project, but includes additional folders and files. In addition, some files that are typical in ASP.NET Web projects have special uses in Dynamic Data.

 

Figure 6 lists the additional elements in a Dynamic Data Web project, and provides a short description of how each element is used.

 

Location

Contains

DynamicData\Content\

Miscellaneous content, including images, the user control used to display filters, and a pager control.

DynamicData\CustomPages\

Optional custom pages that override the scaffolded pages on a per-table basis.

DynamicData\FieldTemplates\

User controls that render individual columns. These include display and edit templates for numbers, Boolean values, text, dates, and relationships.

DynamicData\PageTemplates\

Page templates used for scaffolding. A Dynamic Data project contains a ListDetails template (the default), as well as List, Details, Edit, and Insert templates.

Default.aspx

The site s starting page, with links to all scaffolded tables.

Global.asax

Code to register a data context object with Dynamic Data.

Site.master

The master page that is common to all page templates.

Figure 6: Layout of a default Dynamic Data project.

 

Just Getting Started

This article provides an introduction to Dynamic Data. There are many other aspects and advanced scenarios in this feature, such as:

  • URL routing. This lets you specify how URLs map to tables and which UI is shown.
  • Field templates. These let you write field templates to customize column display and editing.
  • Regular pages. You can use Dynamic Data in any ASP.NET page by placing a DynamicDataManager control on the page and registering data controls with it.
  • Custom pages. You can customize the global page templates on a table-by-table basis by using normal ASP.NET programming techniques.

 

These topics will be covered in future articles.

 

Marcin Dobosz is a developer on the ASP.NET team. He currently is working on the Dynamic Data feature. You can find him online at http://blogs.msdn.com/MarcinOn/.

 

Scott Hunter is a program manager on the ASP.NET team. He currently is working on the Dynamic Data feature. Scott has been working in the industry for more than 20 years and has spent the past seven years building Web applications on the ASP.NET platform. You can find him online at http://blogs.msdn.com/scothu/.

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish