Two worlds of Dynamic Data customization: generic vs schema specific
There are many ways to customize a ASP.NET Dynamic Data site, which can sometimes be a bit overwhelming to newcomers. Before deciding what customization makes sense for you, it is important to understand the two major buckets that they fall into:
- Generic customization: things that apply generically to any table/column.
- Schema specific customization: things that apply to specific tables and/or columns.
They can both very useful depending on your scenario, but it is important to understand how they are different in order to make the right choices. The rule of thumb is that you want to stay in the world of generic customization whenever possible, and only use the schema specific customization when you have to. Doing this will increase reusability and decrease redundancy.
We’ll now look at each in more details.
Generic customization includes everything that you can do without any knowledge of the database schema that it will be applied to. That is, it’s the type of things that you can write once and potentially use without changes for any number of projects. It lets you achieve a consistent and uniform behavior across an arbitrarily large schema, without needing to do any additional work every time you add or modify a table.
Here are some key types of generic customization:
Page Template customization
Under the ~/DynamicData/PageTemplates folder, you’ll find some default Page Templates like List.aspx and Edit.aspx. If you look at them, you won’t find any references to a specific table/column. Instead, they define the general layout and look-and-feel of your pages in an agnostic way.
e.g. if you look at List.aspx, you’ll see a GridView and a LinqDataSource (or EntityDataSource with Entity Framework), but the data source doesn’t have any ContextTypeName/TableName attributes, and the GridView doesn’t define a column set. Instead, all of that gets set dynamically at runtime based on what table is being accessed.
You can easily make changes to these Page Templates, such as modifying the layout, adding some new controls or adding logic to the code behind. It’s a ‘normal’ aspx page, so you can treat is as such, but you should never add anything to it that is specific to your schema. When you feel the need to do this, you need to instead create a Custom Page (see below).
Field Template customization
Under the ~/DynamicData/FieldTemplates folder, you’ll find a whole bunch of field templates, which are used to handle one piece of data of a given type. e.g. DateTime_Edit.ascx handles DateTime columns when they’re being edited.
As is the case for Page Templates, Field Templates should always be schema agnostic. That is, you don’t write a field template that’s only meant to handle a specific column of a specific table. Instead, you write a field template that can handle all columns of a certain type.
For example, in this post I describe a field template that can handle Many To Many relationships. It will work for any such relationship in any schema (though it is Entity Framework specific).
Field Generator customization
Under Page Template above, I mentioned that the GridView didn’t specify a column set. Instead, the way it works is that there is something called a Field Generator which comes up with the set of columns to use for the current table.
The idea is that the Field Generator can look at the full column set for a table, and use an arbitrary set of rules to decide which one to include, and in what order to include them. e.g. it can choose to look at custom model attributes to decide what to show.
Steve Naughton has a great post on writing a custom field generator, so I encourage you to read that for more info on that topic.
Schema specific customization
Any time you make a customization that is specific to a certain table or column, you are doing schema specific customization. Here are the main type of things you can do:
When you want to have a very specific look for a certain page (e.g. for the Edit page for your Product table), a generic Page Template will no longer do the job. At that point, you want to create a Custom Page. Those live under ~/DynamicData/CustomPages/[TableName]. e.g. to have a custom page to edit products, you would create a ~/DynamicData/CustomPages/Products/Edit.aspx.
You can start out with the custom page being an identical copy of the page template, but then you can start making all kind of schema specific changes. For instance, you could define a custom <Fields> collection in the DetailsView, at which point you no longer rely on the Field Generator (discussed below). Taking this one step further, you can switch from a DetailsView into a FormView (or ListView), giving you full control over the layout of the fields.
Another very important type of schema specific customization is model annotation. This is what most introductory Dynamic Data demos show, where you add CLR attributes to the partial class of your entity classes.
For instance, you can add a [Range(0, 100)] attribute to an integer field to specify that it should only take values between 0 and 100. Dynamic Data comes with a number of built-in annotation attributes, and you can easily build your own to add news ways to annotate your model.
The general idea here is that it is cleaner to add knowledge at the model level than to do it in your UI layer. Anything that you can add to describe your data in more details is a good fit for model annotations.
All of the different types of customization that I describe above have useful scenarios that call for them. My suggestion is to get a good understanding of what makes some of them Generic while others are Schema Specific, in order to make an informed decision on the best one to use for your scenarios.