Resources

Using dynamic data in ASP.NET websites

Works at runtime to extract info from data context and apply to template pages for handling CRUD (CREATE, RETRIEVE, UPDATE, DELETE) operations.

Uses info from model (e.g. table relations, field names) to create meaningful pages.

To start:

  1. Create scaffold site that includes default presentation layer templates used by ASP.NET Dynamic Data
  2. Define data context representing data source and model via LINQ to SQL, LINQ to Entities or custom model.
  3. Register data context with websites MetaModel inside Global.asax
  4. Optionally customise URL routing, page and field templates, business logic and validation.

Creating Dynamic Data Website

Can create ASP.NET Dynamic Data website or add to existing site.

Two templates in Visual Studio - ASP.NET Dynamic Data Entities and ASP.NET Dynamic LINQ to SQL.

Data source not specified when creating site - done at later step.

Website Structure

At root of site:

The DynamicData folder has several subfolders and another web.config (which registers handler for System.Web.HttpNotFoundHandler).

The folders (and their naming convention) define pattern used by DynamicData to route requests.

The folders are:

Defining Data Context

Create data context by adding LINQ to SQL Classes (DBML) or ADO.NET Entity Data Model (EDMX) file to project.

Registering Data Context with MetaModel

MetaModel defines connectivity between scaffold templates and the data layer.

Register data context inside Global.asax

At top of Global.asax it is defined as application variable and read-only property:

private static MetaModel s_defaultModel = new MetaModel();

public static MetaModel DefaultModel { get { return s_defaultModel; } }

The RegisterRoutes method is called at application start. This method is used to connect data source to MetaModel. The DefaultModel.RegisterContext() method takes type name of data context, setting ScaffoldAllTables to true ensure site will return all tables in data context.

A DynamicDataRoute should be added, specifying the form that URIs should take and any action constraints that are appropriate.

public static void RegisterRoutes(RouteCollection routes) (DefaultModel.RegisterContext(typeof(NorthwindDataContext), new ContextConfiguration() { ScaffoldAllTables = true });

routes.Add(new DynamicDataRoute("{table}/{action}.aspx") {
Constraints = new RouteValueDictionary( new action="List|Details|Edit|Insert"}), Model= DefaultModel });
}

Can then access data pages, for example to list contents of Products table issue:

http://localhost/myApp/Products/List.aspx

Custom Routing

Uses same routing features from System.Web.Routing as ASP.NET MVC.

Routing engine maps URIs base don user action to actual pages in site - makes URIs easier to understand for users and search engines.

For example a DynamicDataRoute class indicates URI should be mapped to table/action.aspx:

routes.Add(new DynamicDataRoute("{table}/{action}.aspx")  
{
Constraints = new RouteValueDictionary( new action="List|Details|Edit|Insert"}),Model= DefaultModel })

will ensure that call to http://mysite/Products/Edit.aspx?ProductID=1 will be routed to /DynamicData/PageTemplates/Edit.aspx with the page knowing to edit the Products table and its record with a ProductID of 1.

Editing URI structure

Could switch table and action {action}/{table} and get same results for the URI, e.g.: http://mysite/Edit/Products?ProductID=1

Editing Route Table To Show List And Details On Same Page

Dynamic Data page templates include ListDetails.aspx that supports viewing a list of items and details for one selected item. Also supports insertion and deletion of items. By default this page nit used, but can activate it by removing existing routing and adding the following for List and Details:

routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx")  
{
Action = PageAction.List,
ViewName = "ListDetails",
Model = DefaultModel
}

routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx")
{
Action = PageAction.Details,
ViewName = "ListDetails",
Model = DefaultModel
}

Custom routes to specific pages

Create new folder in CustomPages folder and name folder with entity name from model.

Place appropriate action pages (List.aspx, Edit.aspx, etc.) into folder.

Default routing will pick these pages up in preference to those in PageTemplates folder.

Adding MetaData to Data Context

Data Context made up of partial classes.

Can extend these partial classes with metadata defining how fields are to be displayed and validated.

Start by adding partial class to App_Code directory and give it same name as a class in data context.

Then create related metadata class (using EntityMetadata naming convention).

Inside metadata class redefine properties contained in data context class - note these should be simple object types because the underlying type has already strongly typed them.

Mark properties with appropriate MetadataType attributes.

[MetadataType(typeof(ProductMetatdata}]
public partial class Product {}

public class ProductMetaData
{
public object ProductID { get; set; }

// Hide column from display
[ScaffoldColumn(false)]
public object QuantityPerUnit{ get; set; }

//// Rename column to price and display as currency when not editing
[DisplayFormat(ApplyFormatInEditMode=false, DataFormatString="{0:C}")]
[DisplayName="Price"]
public object UnitPrice { get; set; }
}

Custom Validation

Can also apply validation attributes such as Range, StringLength, Required, RegularExpression in similar fashion, e.g.:

[Range(1, 144, ErrorMessage = "Quantity between 1 and 144")]  
public object ReorderLevel { get; set; }

Custom Validation With Partial Methods

Data content model includes partial methods within the Extensible Method Definitions region of code generated by LINQ to SQL

For each property there is a OnChanging and OnChanged partial method.

Can use these partial methods to write customised validation rules.

Besides having access to all fields within record the OnChanging method is passed the value to which the property is being changed.

If encounter problem throw ValidationException.

Custom Field Templates

FieldTemplates used to render appearance and functionality of data context properties.

Controls named as either edit or display controls for specific data type, e.g. DateTime.ascx and DateTime_Edit.ascx

Can edit existing field template controls or create new ones.

If creating new control use metadata to specify which properties in data model use the new control.

Customise Existing Field Templates

Can modify like any other control, e.g. adding client side code, appearance, processing logic, etc.

Creating New Field Template Control

Copy existing control in Dynamic Data / Field Templates folder or select Dynamic Data Field template from Add New Item dialogue.

When using Dynamic Data Field template two controls are generated; one for display (ControlName.ascx) and the other for editing (ControlName_Edit.ascx).

By default display is a Literal control whilst edit includes a TextBox and validation controls.

For example may want to use Calendar control when in edit mode. Leave display control alone, but edit control modified so that the markup includes a calendar control and the code behind file overrides OnDataBinding to setup Calendar control.

<asp:Calendar ID="Calendar1" runat="server"/>
protected override void OnDataBinding(EventArgs e)
{
base.OnDataBinding(e);
DateTime dte = DateTime.Parse(this.FieldValue.ToString());
Calendar1.SelectedDate = dte;
Calendar1.VisibleDate = dte;
}

Then apply the control to fields via metadata.

public class EmployeeMetadata
{
[UIHint("CalendarPicker")]
public object HireDate { get; set; }
}

Custom Page Templates

Specific to single entity in data context.

Create new folder under CustomPages with same name as entity object.

Copy one or more templates from PageTemplates folder into new folder.

Dynamic Data routing will look first in CustomPages/EntityName for action pages such as Edit.aspx, List.aspx, etc. If no action page found then version in PageTemplates folder used.

A common edit is to bind the GridView control more tightly with specific entity. Do this by setting AutoGenerateColumns property to false and then adding a series of DynamicField properties that represent the bound data.

Adding Dynamic Data Scaffolding To Existing Website

First define data context for site - can be LINQ to SQL, ADO.NET Entity Framework or a custom data context.

Edit Global.asax to register context and enable routing - can copy from Global.asax for blank Dynamic Data site.

Copy DynamicData folder from blank Dynamic Data site into existing site.

Enabling Dynamic Data Inside Webpage

Can use Dynamic Data inside pages that do not use scaffolding or routing.

Have standard ASP.NET website that includes ADO.NET Entity Data Model for working with database.

Can add EntityDataSource to Default.aspx. This control can be used for selecting, inserting, updating and deleting.

<asp:EntityDataSource ID="EntityDataSource1" runat="server" ConnectionString="name=northwindEntities" DefaultContainerName="northwindEntities" EnableDelete="True" EnableFlattening="False" EnableInsert="True" EnableUpdate="True" EntitySetName="Products" />

Next add data display control to page.

<asp:GridView ID="GridView1" runat="server" DataSourceID="EntityDataSource1" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="True">

<Columns>

<asp:CommandField ShowEditButton="True" />

</Columns>

</asp:GridView>

Finally add code to Page_Init to enable Dynamic Data:

protected void Page_Init(object sender, EventArgs e)
{
GridView1.EnableDynamicData(typeof(northwndModel.Product));
}

Downloads