Introduction
This article is a beginner's tutorial on ASP.NET dynamic data websites. This article describes ASP.NET dynamic data in brief and implements a small dynamic data website for explanation.
Background
There are quite a few websites running on the internet and a lot of intranet applications being used which mainly provide the user interface
to manipulate databases. The websites were developed as ASP.NET forms typically retrieving, inserting, updating data. With ASP.NET dynamic data websites, creation of such data centric web
applications has become very easy. Dynamic data websites are also very useful in creating website administration portals where the administrator
can easily access the database from a web based interface created by the ASP.NET dynamic data project.
Dynamic data websites work on top of the scaffolding framework from Microsoft. The basic idea behind
a dynamic data website is that once we have a database
ready with us, we can create a data context for this database using either "LINQ to SQL" or "Entity
Framework". Once we have the data context ready with
us, we can use this context, and the web pages that will perform database operations will be generated at runtime. The important thing to notice is
that a dynamic data website generates pages at runtime and it is not some auto generated code by
Visual Studio. It does use some template pages
and controls to render the actual data, which in fact is a good thing because it gives us the possibility of customization as per our needs.
If we try to visualize the high level architecture of dynamic data websites:
The Solution
Let us try to work out a small example to understand how we can create and customize a dynamic data website. We will be using a small
database called LaptopShop. The database contains only two tables. We will try to access this simple database by creating a dynamic data website.
Creating a dynamic data website
Let us start by creating a new dynamic data website. We can create a dynamic
data website or a dynamic data project. Once we have the dynamic data website created, the first thing
we have to look into is how to use the database. Let us put the database in the
APP_Data directory..
The next thing we need to do is add a data source mapping by using wither LINQ to SQL or
the Entity Framework. Let us use Entity Framework for this article.
Irrespective of the type we are choosing here, the basic philosophy will remain the same.
Entity Framework has created the data context and entities for our database.
The next thing we need to do is look into the global.asax file. This file contains the code for all the routing mechanisms for rendering the pages.
What we need to do here is specify our data context so that it can be used in this dynamic data website.
Notice that I have set scaffoldAllTables
to true. This would indicate that I want all the tables and all the columns rendered as is and it
should be possible to manipulate all the fields using our website once we run the application.
The main page of the application shows the list of tables:
The Laptop Table when viewed from the application:
Notice that the dynamic data site is intelligent enough to identify the relationship between the tables and gives me the possibility to use the relationships for better management.
The Manufacturer table when viewed from the application shows the relation with the Laptop table:
While inserting new data, I can use the relationships between tables in a meaningful way:
Viewing selective tables from the database
What we have done so far has created the dynamic data website for us but it is showing all the tables. What if
we don’t want to see some of the tables? If we want to see
only a few tables from the database then we will have to
take the scaffolding control in our hand. So we first need
to disable the default scaffolding as:
DefaultModel.RegisterContext(typeof(testDbEntities), new ContextConfiguration() { ScaffoldAllTables = false });
Now the idea of the dynamic website is that the runtime will check for the scaffolding status for all the tables and then decide which table should be rendered to the user.
We need information about the table and the scaffolding status. So if we have the default scaffolding turned off, we will have to change
the generated entities class to have custom tables rendered on pages.
The problem in doing it is that even if we change the entity class in the generated code the application won't
work because when the entity classes are generated again, our changes will be lost. So we cannot change the generated classes' code.
The generated classes are partial classes and that is the key to customizing these classes. We can in fact
have the
partial classes with the same name in our App_Code folder and this class will be merged with the generated class and thus effectively have our changes preserved.
So we have the scaffolding enabled on a few tables and we need to use the ScaffoldTable
attribute of the entity class for that table.
Let's say we want to show only the Laptops table, then we need to have a partial class for that with the ScaffoldTable
attribute set to true.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace DynamicDataTest
{
[ScaffoldTable(true)]
public partial class Laptop
{
}
}
Now if we run the application, we can only see the Laptops table and not the Manufacturer table.
So for all the tables, we need to have the possibility for the user to manipulate data from our dynamic data website.
Let us do this for the other table too.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace DynamicDataTest
{
[ScaffoldTable(true)]
public partial class Manufacturer
{
}
}
Viewing selective columns from a table
The default settings of the dynamic data website takes care of not displaying the primary key column on the pages and displaying the foreign key columns
in some meaningful way (i.e., link to the related table). But there could be scenarios when we want to show only some set of columns to the user. If we want to do that we will have
to define a Metadata class for the entity classes and then set the ScaffoldColumn
attribute to false for every column we don't want to display in pages.
Let us remove the column processor from the laptop table and see how it works. So the code for this will look like:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace DynamicDataTest
{
[ScaffoldTable(true)]
[MetadataType(typeof(LaptopMetadata))]
public partial class Laptop
{
}
public class LaptopMetadata
{
[ScaffoldColumn(false)]
public global::System.String Processor;
}
}
Now if we run the application, we will not see the processor column in the laptop table.
Customizing field templates
One more important thing remaining is to control the look of our website. The dynamic data website uses page templates and control templates to generate pages at run time.
If we need to change the appearance of the website then we can change these templates or can have our own templates and have them working in unison with the dynamic data website.
For now I will just add a new control to render the text type of the data and then use this control with the
screen size column of the laptop table. To do this I need to add a field template and then customize it. I am just adding some
static text in front of actual values to illustrate but these controls can be customized with endless possibilities.
The change is the default text control:
<%@ Control Language="C#" CodeBehind="Text2.ascx.cs" Inherits="DynamicDataTest.TextField2" %>
Value =
<asp:Literal runat="server" ID="Literal1" Text="<%# FieldValueString %>" />
The change is the edit text control:
<%@ Control Language="C#" CodeBehind="Text2_Edit.ascx.cs" Inherits="DynamicDataTest.Text2_EditField" %>
New value =
<asp:TextBox ID="TextBox1" runat="server" Text='<%# FieldValueEditString %>' CssClass="DDTextBox"></asp:TextBox>
<asp:RequiredFieldValidator runat="server" ID="RequiredFieldValidator1"
CssClass="DDControl DDValidator" ControlToValidate="TextBox1" Display="Static" Enabled="false" />
<asp:RegularExpressionValidator runat="server" ID="RegularExpressionValidator1"
CssClass="DDControl DDValidator" ControlToValidate="TextBox1" Display="Static" Enabled="false" />
<asp:DynamicValidator runat="server" ID="DynamicValidator1"
CssClass="DDControl DDValidator" ControlToValidate="TextBox1" Display="Static" />
and finally, I will have to use my laptops metadata class to use this control using
the UIHint
attribute on the property
of the entity class. Having done that, my class will look like:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace DynamicDataTest
{
[ScaffoldTable(true)]
[MetadataType(typeof(LaptopMetadata))]
public partial class Laptop
{
}
public class LaptopMetadata
{
[ScaffoldColumn(false)]
public global::System.String Processor;
[UIHint("Text2")]
public global::System.String ScreenSize
{
get;
set;
}
}
}
Now when we run the application, we can see that the new control is being used to render the screen size field both in View and Edit mode.
So we saw that the looks of the default dynamic data website can be customized by customizing the page templates and field templates.
Points of Interest
I have tried to explain ASP.NET Dynamic Data websites using this small application. With
a dynamic data website, making a data centric website is very easy.
There are a few points to remember:
- An ASP.NET dynamic data website can be created using either "LINQ to SQL" or "Entity Framework".
- Partial classes can be used to add custom attributes to entity classes and have finer control on scaffolding.
- MetaData classes can be used to control the look and behavior of individual columns of tables.
- Page templates and field templates can be customized to control the appearance of the website.
- Important: Partial methods like
OnChanging
inside entity classes can be used to have more control over the behavior
on insert and update. We have not looked into that, but that is one more aspect that is important from
a dynamic data website's perspective.
History
- 02 May, 2012: First version.