In a traditional data driven web site, you need to individually create web forms necessary to get the data in and out of the database tables. ASP.NET Dynamic Data features allow you to automate this functionality. ASP.NET Dynamic Data allows you to create extensible data driven web applications with little or no coding from your side. ASP.NET Dynamic Data automatically reads the database schema for you and generates data display and data entry pages on the fly. You can, of course, customize the resultant application if needed. The ASP.NET Dynamic Data Web Site project templates create a base project with necessary web forms and user controls that you can customize to suit your needs. However, in some cases creating a separate project is undesirable and you may want to integrate the Dynamic Data features with an existing web site. In this step-by-step article you will learn how this can be accomplished.
Dynamic Data Web Site Project
Before we proceed to see how dynamic data features can be utilized in existing web sites, it is worthwhile to take a quick look at Dynamic Data Web Site project templates.
Visual Studio 2010 provides two web site project templates related to dynamic data viz. ASP.NET Dynamic Data LINQ to SQL Web Site and ASP.NET Dynamic Data Entities Web Site. Depending on your data model type (LINQ to SQL based or Entity based) you need to select the appropriate project template. Figure 1 shows these project templates.
Figure 1: Dynamic Data web site project templates of Visual Studio 2010
The default project template includes several web forms and user controls arranged in a specific folder structure under the DynamicData folder (see Figure 2).
Figure 2: Folder structure of a dynamic data web site
As you can see the DynamicData folder contains several sub-folders such as FieldTemplates and PageTemplates. Though we won't discuss them in detail here, we will use FieldTemplates folder later in our examples.
The default project template is not connected with any database as such and you need to create the required data models (LINQ to SQL classes or Entities) to make it work. At run time dynamic data uses scaffolding to generate web pages for each table in the database. You can then view or edit the table data.
The default project templates work well if you wish to create an independent web site. However, at times you require that dynamic data be used with existing web sites i.e. without using scaffolding. In such cases a commonly suggested solution is to copy paste the DynamicData folder from the Dynamic Data project template to an existing web site and then change a few things here and there. The drawback of this approach is that you may end up having many files and user controls in your web site (though arranged inside the DynamicData folder) that are not actually using at all. In the following sections, you will learn how to enable dynamic data features for ASP.NET data controls such as GridView, DetailsView and FormView from scratch.
Sample Database and LINQ to SQL class
Throughout this article you will use a SQL Server database with a single table named BlogPosts. The BlogPosts table is intended to store blog entries. The table schema and columns of BlogPosts table are deliberately over simplified for the sake of keeping things simple but you can extend the concepts discussed here to any other table.
The schema of BlogPosts table is shown in Figure 3.
Figure 3: Schema of BlogPosts table
The BlogPosts table consists of five columns namely Id, Title, Content, PublishDate and AllowComments. The column names are self-explanatory. The Id column is the primary key and is marked as an identity column.
Before you go ahead, create a new ASP.NET Empty Web Site project and add a SQL Server database into its App_Data folder. Create the BlogPosts table matching the schema as shown in Figure 3 using Server Explorer. Then add a LINQ to SQL class to the web site's App_Code folder and drag and drop BlogPosts table from the Server Explorer onto the surface of .dbml file. Doing so will create a LINQ to SQL class (BlogPost) as shown in Figure 4.
Figure 4: BlogPost LINQ to SQL class
In the examples that follow you will use LINQ Data Source control configured to use the BlogPost class to get the data in and out of the database. Also make sure to add some sample data to the BlogPosts table.
Enabling Dynamic Data for Data Controls
Now that you are ready with the BlogPosts table and related LINQ to SQL class, let's see how to enable dynamic data for ASP.NET data controls. In this example you will use GridView control to display and edit entries from BlogPosts table.
Begin by adding a new web form into the web site and drag and drop a LINQ Data Source control and a GridView control on it. Configure the LINQ Data Source control to read and write data using BlogPost class (Figure 5).
Figure 5: Configuring LINQ data source control
DataSource property of the GridView control to LinqDataSource1 and open the Fields dialog of the GridView as shown in Figure 6.
Figure 6: Configuring DynamicField columns of GridView
Notice the "Available fields" section in Figure 6. In addition to field types such as BoundField and TemplateField, it also lists DynamicField. A DynamicField represents a data field that makes use of ASP.NET Dynamic Data features. At first glance, a DynamicField resembles to a BoundField. However, a DynamicField supports dynamic data features that are not supported by BoundField. These features include:
- Automatically rendering a UI template depending on the data type of underlying database column.
- Providing a way to customize the default UI rendered.
- Adding data validation capabilities based on the database schema.
Add five DynamicField columns to the GridView and set their HeaderText and DataField properties to the corresponding properties of the BlogPost class. Also, add a CommandField of type Edit-Update-Cancel so that GridView data can be modified.
Now, go in the code file of the web form and in the Page_Init event handler add the following line of code:
EnableDynamicData() is an extension method for data controls such as GridView, DetailsView and FormView that enables dynamic data features for the data control under consideration. The
EnableDynamicData() method accepts the type of data model that the data control will be dealing with (BlogPost in this example).
Run the web form and see how the GridView displays and edits the data. At this point you may not be able to distinguish between a GridView without dynamic data features and a GridView using dynamic data features. Now, click on the Edit button of any of the GridView row and deliberately enter some character data in PublishDate column. Click Update in an attempt to save the data. Surprisingly you will be shown with an error as in Figure 7.
Figure 7: Dynamic Data features validate data
* next to the PublishDate textbox. Enabling dynamic data features automatically validate the data against the database schema and show error if necessary.
In the next section you will learn how to enhance and customize the default validation mechanism provided by dynamic data.
The first thing you would like to change in the preceding example is the way validation errors are displayed. Internally dynamic data makes use of certain CSS classes that control the appearance of the validation errors. These classes are named DDControl and DDValidator (You can find these names if you see HTML source in the browser). To create these classes open the CSS file of your web site and place the DDControl and DDValidator classes as shown below:
Then add a reference to the style sheet from the web form like this:
Next, drag and drop a Validation summary control above the GridView control and run the web form again. This time you should see error messages with your CSS style attributes.
Figure 8: Customizing appearance of validation errors
Also notice how the Validation Summary control is automatically displaying a relevant error message.
Sooner or later you will come across situations where the default validation mechanism of dynamic data will prove to be inadequate and you will require further customization. Fortunately, dynamic data gives good amount of control over the validation process through data annotations. Let's see how.
The System.ComponentModel.DataAnnotations namespace provides several attributes that can be used to define metadata for dynamic data. These attributes can be applied on class properties to specify the validation criteria. In the above example the data model is a LINQ to SQL class and directly modifying the BlogPost class to place data annotation attributes can create trouble at a later stage since LINQ to SQL class can be regenerated wiping out our changes. The recommended approach is to create a metadata class and place the data annotation attributes there. Here is how you can create a metadata class for BlogPosts class (you should add this class in the App_Code folder).
Notice the BlogPostMetadata class carefully. It contains property definitions for the properties on which you wish to enforce some validation. The
[StringLength] data annotation attribute is used to ensure that the property value has certain minimum and maximum length. The ErrorMessage property of the
[StringLength] attribute governs the error message as outputted in the Validation Summary control. The [Range] attribute ensures that the
PublishDate value is within some date range.
Currently the BlogPostMetadata class is an independent class nowhere related to the data model class BlogPost. To link them together you will create a BlogPosts partial class and decorate it with
The [MetadataType] attribute allows you to associate metadata class with the data model class.
Once you modify your application as explained above run the web form again and try to violate some validation rule (say enter a
PublishDate not within the specified date range) and you will see the error messages displayed accordingly.
Figure 9: Validations using data annotation attributes
Creating Custom Editors for Data Fields
In the preceding examples the edit mode template of some data entry fields is not very convenient. For example, the Content field has a big chunk of text data and the single line textbox is not suitable for entering such big chunks of text data. Similarly, making
PublishDate field as a plain textbox calls for entering dates manually rather than picking them up from a calendar or date picker. Luckily, dynamic data allows you to customize the user interface of various dynamic fields.
It would be worthwhile to note how dynamic data differs than the usual template fields of data controls. A template field of a data control is confined to that instance of control. For example, if you have three GridView controls on three independent web forms and you wish to have a date picker for the
PublishDate field then you will need to design the template field thrice even if the user interface is exactly same. In dynamic data, however, things are quite different. You design a user interface template just once and then simply associate that template wherever you need it irrespective of any data control or web form. If you don't provide template for some fields, they will use the default ones.
Now let's see how a custom template can be built. You will create custom templates for plain text fields, multiline text fields, bit fields and date fields. Though we won't discuss all of them here, templates of date field are discussed below. Other templates can be found in the source code download accompanying this article.
Begin by adding a new folder to your web site and name it as DynamicData. This nomenclature is necessary for dynamic data to pick the templates up properly. Inside the DynamicData folder create a subfolder named FieldTemplates. This folder will contain all the custom field templates. Each field template is a User Control that defines the look and feel of the template in read only, edit and insert modes. The dynamic data naming convention requires that edit and insert templates be suffixed by _edit and _insert respectively. Thus, if the display template has name MyTemplate then the edit and insert mode templates will be MyTemplate_Edit and MyTemplate_Insert respectively.
Now, right click on the FieldTemplates folder and select "Add New Item" option. In the "Add New Item" dialog locate Dynamic Data Field and name it DateField.ascx. You will find that two user controls get added for you - DateField.ascx and DateField_Edit.ascx.
Figure 10: Adding a new dynamic data field
If you observe the code file of the DateField dynamic data field, you will find that the user control class inherits from FieldTemplateUserControl base class. Switch to the HTML source of DateField.ascx and you find the following fragment of markup:
As you can see, there is a Literal server control whose Text property is bound with
FieldValueString property. The
FieldValueString property comes from the FieldTemplateUserControl base class and represents the string value of the underlying data field. You can customize the user interface if you so wish but make sure to data bind with the
FieldValueString property so that field value is displayed correctly.
The code file of DateField.ascx contains an overridden property DataControl that simply returns the data bound control (Literal1 by default).
If you changed the default UI, you should also change the
DataControl property to return the appropriate control reference.
At times, you may want to format the field value before it gets displayed in the data control. For example, you may want to format the PublishDate in dd MMM yyyy format and then display in the GridView. To do such things you can override the OnDataBinding() method as shown below :
FieldValue property gives a reference to the actual data field value and is of type Object. You can change it to suit your requirements.
Next, open DateField_Edit.ascx and drag and drop a Calendar control on it. Then data bind
VisibleDate properties to
FieldValueEditString property as shown below:
FieldValueEditString property gives you the string representation of the field value in edit mode.
Now, open the code file and change the
DataControl property definition like this:
This completes the
DateField dynamic data field. Next step is to associate this custom field to the PublishDate property. There are two ways to perform this association – using
[UIHint] attribute in the metadata class and using
UIHint property of the DynamicField class. Let's see both of them one by one.
Open the BlogPostMetadata class you created earlier and decorate
PublishDate property with
[UIHint] attribute as shown below:
[UIHint] property specifies the name of the dynamic data field template that is to be used for displaying and editing the property under consideration. Remember that because of the naming conventions you followed earlier (_
Edit for field template in edit mode) dynamic data automatically uses the correct field templates based on the current mode of a data control (Read only, Insert or Edit).
To associate a field template at data control level, open the fields dialog of GridView and set
UIHint property of DynamicField columns to appropriate field template name (see Figure 11).
Figure 11: Setting UIHint property of a DynamicField
Ok. Now, let's put what you learnt so far into an example that uses FormView and DynamicControl. The DynamicControl is a server control closely matching with DynamicField you used earlier. However, since it is a separate control you need to use it inside a TemplateField. Doing so also allows you to stuff other controls or markup around the DynamicControl for the sake of customization.
Once you place the FormView on the web form, design its ItemTemplate, EditItemTemplate and InsertItemTemplate as you normally do. Keep in mind that you should use DynamicControl to display data in all the three templates just mentioned.
Figure 12: DynamicControl server control
DataField property of the DynamicControl allows you to bind it with the underlying data field. Also, set
UIHint property of DynamicControl instances to appropriate dynamic data field templates (make sure to temporarily comment out the
[UIHint] attribute if you have placed it in the metadata class). The Figure 13 shows a FormView in read only mode whereas Figure 14 shows it in edit mode. Notice how multiline textboxes and calendar is being displayed due to
UIHint property (See code download accompanying this article for all the field templates used by this example).
Figure 13: Custom dynamic data field templates in read only mode
Figure 14: Custom Dynamic data field templates in edit mode
Providing Default Values
When a data control switches to Insert mode, by default its fields will be blank. You may want to provide some default values to the insert mode templates so that the user can simply modify them or fill in only the required ones. To achieve this behavior, you can call the
EnableDynamicData() method as shown below:
Notice the second parameter of the
EnableDynamicData() method. It specifies the default values for data fields. After specifying the default values if you switch the FormView to the insert mode, you should see something similar to Figure 15.
Figure 15: Specifying default values for dynamic data fields
Using Dynamic Data Manager Control
In the examples so far you used
EnableDynamicData() extension method on individual data controls to enable dynamic data features. If you are using dynamic data features with many data controls, enabling them declaratively rather than via code can be convenient. The Dynamic Data Manager server control allow you to do just that. The Dynamic Data Manager control acts as a mediator between dynamic data features and various data controls on the web form.
To use a Dynamic Data Manager control, firstly you need to place it on the web form and configure its DataControls collection as shown in Figure 16.
Figure 16: DataControlReference collection editor
Additionally, you need to add a couple of lines of code in Global.asax file.
The MetaModel class allows you to register the LINQ to SQL data context with dynamic data. It does so with the help of
Once you register your data context with dynamic data as shown above, you can run the web form to check if it works exactly as before.
ASP.NET Dynamic Data features allow you to create extensible data driven web sites easily. You can also use dynamic data in an existing web site. The
EnableDynamicData() extension method enables dynamic data features for data controls such as GridView, DetailsView and FormView. Alternatively, you can also use Dynamic Data Manager control to enable dynamic data for these controls. Once enabled you can take advantage of data validation and field customization techniques. Validating data is a matter of using data annotation attributes whereas creating custom field templates involve developing required field template user controls. Once created the field templates can be associated with the data controls using
[UIHint] attribute or
Bipin Joshi is a blogger, author and a Kundalini Yogi who writes about apparently unrelated topics - Yoga & Technology! A former Software Consultant and trainer by profession, Bipin is programming since 1995 and is working with .NET framework ever since its inception. He is an internation...
This author has published 7 articles on DotNetSlackers. View other articles or the complete profile here.
Please login to rate or to leave a comment.