maggio 07, 2012

Programming Asp.Net: An introduction to ASP.NET dynamic data from a beginner's perspective.


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:
dynamic data article image

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.
dynamic data article image

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.
dynamic data article image
Entity Framework has created the data context and entities for our database.
dynamic data article image
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.
dynamic data article image
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:
dynamic data article image
The Laptop Table when viewed from the application:
dynamic data article image
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:
dynamic data article image
While inserting new data, I can use the relationships between tables in a meaningful way:
dynamic data article image

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.
dynamic data article image
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.
dynamic data article image

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.
dynamic data article image
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.
dynamic data article image
dynamic data article image
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.

Nessun commento:

Posta un commento