I have been anxiously awaiting the Dynamic Data release. And now that it is here (it was released with VS 2008 and .Net 3.5 SP1) I decided I would start getting a feel for what is has to offer by building a real simple Dynamic Data web site that allows you to browse the 5 core Northwind tables – Customers, Employees, Orders, Products and Suppliers. Read on for the details and don’t forget to download the code. DiscountASP hasn’t quite upgraded to SP1 so I don’t have a live demo setup. Hopefully they will get the upgrade completed soon, but I made sure to include lots of screen shots so you can get a good idea of what the screens look like.
Download

What is Dynamic Data?
I try to keep a close eye on ASP.NET, but I didn’t know Dynamic Data was shipping as part of SP1. I asked around the office and found out this took a few other people by surprise too. And more than a few people had actually never heard of Dynamic Data. In case you fall into that category, here are a couple of quotes that describe what DynamicData is all about.
From Wikipedia …
ASP.NET Dynamic Data is a web application scaffolding framework from Microsoft, shipped as an extension to ASP.NET, that can be used to build data driven web applications. It exposes tables in a database by encoding it in the URI of the ASP.NET web service, and the data in the table is automatically rendered to HTML. The process of rendering can be controlled using custom design templates. Internally, it discovers the database schema by using the database metadata.
From asp.net …
ASP.NET Dynamic Data provides a framework that enables you to quickly build a functional data-driven application, based on a LINQ to SQL or Entity Framework data model. It also adds great flexibility and functionality to the DetailsView, FormView, GridView, and ListView controls in the form of smart validation and the ability to easily change the display of these controls using templates.
So for this demo app, I am planning on using Dynamic Data to build a web application that allows me to browse the Northwind database.
Create the Dynamic Data Web Site
To get started building a Dynamic Data Web Site, you do the usual File -> New -> Web Site and select either the Dynamic Data Entities Web Site or Dynamic Data Web Site templates. If you plan on using the ADO.NET Entity Framework for data access you can select the first option, otherwise if you are using LINQ to SQL you select the second template. For this example I am using LINQ to SQL so I chose the Dynamic Data Web Site template.

When VS finishes loading, you will notice a number of files/folders have been included in the solution. The solution includes a DynamicData folder that is filled with other folders and each is filled with both UserControls and regular ASP.NET Pages.

Create and Register the LINQ to SQL DataContext
I am going to use LINQ to SQL to access the my Northwind data, so I used the VS designer create the LINQ to SQL classes for the tables I want by dragging my tables over from the server explorer and dropping them onto the design surface.
After creating the DataContext, I update the Global.asax and register my NorthwindDataContext with the DynamicData system. The web site template generates the code that handles all of this, you just have to read the comments and plug in your custom context type. Here is what it ends up looking like …
public static void RegisterRoutes(RouteCollection routes)
{
MetaModel model = new MetaModel();
// IMPORTANT: DATA MODEL REGISTRATION
// Uncomment this line to register LINQ to SQL classes or an ADO.NET Entity Data
// model for ASP.NET Dynamic Data. Set ScaffoldAllTables = true only if you are sure
// that you want all tables in the data model to support a scaffold (i.e. templates)
// view. To control scaffolding for individual tables, create a partial class for
// the table and apply the [Scaffold(true)] attribute to the partial class.
// Note: Make sure that you change "YourDataContextType" to the name of the data context
// class in your application.
model.RegisterContext( typeof(NorthwindDataContext), new ContextConfiguration() { ScaffoldAllTables = true });
// The following statement supports separate-page mode, where the List, Detail, Insert, and
// Update tasks are performed by using separate pages. To enable this mode, uncomment the following
// route definition, and comment out the route definitions in the combined-page mode section that follows.
routes.Add(new DynamicDataRoute("{table}/{action}.aspx") {
Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert"}), Model = model
});
// The following statements support combined-page mode, where the List, Detail, Insert, and
// Update tasks are performed by using the same page. To enable this mode, uncomment the
// following routes and comment out the route definition in the separate-page mode section above.
//routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx") {
// Action = PageAction.List,
// ViewName = "ListDetails",
// Model = model
//});
//routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx") {
// Action = PageAction.Details,
// ViewName = "ListDetails",
// Model = model
//});
}
And really after you have done this you have a pretty nice looking and functional web site. A landing page that lets you know about what tables are available …

Grids for viewing the contents of these tables (paging and sorting included) …

And pages for Inserting, Updating and viewing Details …

Customization
If I was happy with how all of the default pages look, I could have stopped here and had a functional web application that supports basic CRUD operations. That’s pretty cool. And that took all of what … 5 minutes? But what if I would like to change a few things?
Customizing the List Page Template
The List template is located in the DynamicData/PageTemplates folder. The default List page look pretty good, but I wanted to see what it would take to make a few changes. So I opened the List.aspx page and started making my changes.
- First, I added a black border by wrapping the GrdView in a series of DIVs that use background images to style the border.
- Next, I increased the PageSize from 10 to 15.
- Then added a different Data Pager
- Finally, I want my site to be read-only so I removed the Insert, Edit and Delete links
Nothing too major, but styles provide quite a bit of change.

Customizing the Details Page Template
Next, I made similar changes to the Details page template.

Adding Custom Metadata to the Model
There are a few things that you will notice in the screen shots above with my custom pages that are different from the default pages.
- The grids column counts are different (my custom pages have fewer columns)
- Some of the column headers have different names
- Some of the grid’s cell values are formatted differently
- The display name for the table
To customize these items, you need to create a metadata class that provides Dynamic Data with a little more information about your entities. I will be honest, this part seems a little weird to me, but that might just be because it is new. Anyway, to accomplish this you need to create two more classes for each of the classes in your DataContext. So for my 5 table sample, I need to create 10 more classes to attach my metadata.
First you add a partial class with the same name of the entity class in the data model and then apply an attribute to this partial class that ties it to the additional metadata we have defined for the class. The code snippet below is what does this for the Order entity in our sample application. The following bit of code tells Dynamic Data the following …
- The display name for the Order table is ‘My Orders’ – Applied with the TableName attributes
- The OrderDate, ShippedDate, ShipAddress and ShipCity columns all have overridden display names – Applied with the DisplayName attribute
- The OrderDate and ShippedDate columns have a custom format – Applied with the DisplayFormat attribute
- The RequiredDate, ShipVia, Freight, ShipName, ShipPostalCode, and ShipCountry columns should be hidden from the UI – Applied with the ScaffoldColumn attribute
// Attach the OrderMetadata to the Order class
[MetadataType(typeof(OrderMetadata))]
public partial class Order {}
[TableName("My Orders")]
public class OrderMetadata
{
// Override the display name
[DisplayName("Date Ordered")]
// Format the Date
[DisplayFormat(DataFormatString="{0:d}")]
public object OrderDate { get; set; }
// Override the display name
[DisplayName("Date Shipped")]
// Format the Date
[DisplayFormat(DataFormatString = "{0:d}")]
public object ShippedDate { get; set; }
// Override the display name
[DisplayName("Address")]
public object ShipAddress { get; set; }
// Override the display name
[DisplayName("City")]
public object ShipCity { get; set; }
// Columns I want hidden
[ScaffoldColumn(false)]
public object RequiredDate { get; set; }
[ScaffoldColumn(false)]
public object ShipVia { get; set; }
[ScaffoldColumn(false)]
public object Freight { get; set; }
[ScaffoldColumn(false)]
public object ShipName { get; set; }
[ScaffoldColumn(false)]
public object ShipPostalCode { get; set; }
[ScaffoldColumn(false)]
public object ShipCountry { get; set; }
}
Conclusion
Well that was my first pass through building a Dynamic Data site. I am pretty impressed and I am looking forward to exploring this further – stay tuned.
That’s it. Enjoy!