Click here to Skip to main content
15,884,298 members
Articles / Web Development / ASP.NET
Article

Building ASP.NET Web Pages Dynamically in the Code-Behind

Rate me:
Please Sign up or sign in to vote.
4.00/5 (13 votes)
25 Apr 2008CPOL15 min read 212.7K   12.9K   56   13
This article shows a technique for building ASP.NET web pages where the entire page contents are created dynamically in code-behind.

Introduction

Think about how web pages have been built over the years. If you were around for the early days (c. 1995), you probably built a web as pure HTML using either a text editor or some early HTML editor. Within a few years, there were scripting language technologies such as classic ASP with VBScript. Programmers began building web pages as mostly static HTML, with some VBScript thrown in to build out dynamic or data-driven areas — but the page was still mostly static HTML. Then ASP.NET came along and introduced the code-behind concept. C# and VB.NET in the Visual Studio environment made writing bug-free code much easier. Now, your entire page could be built out programmatically from code. So what did you do? You probably just brought your class ASP programming style to ASP.NET and continued to build pages as a mix of static text and code. This technique was even simplified by the "toolbox" concept in Visual Studio which provided some pretty impressive support for dropping controls on pages and setting their properties — about as good as you can get to build an entire web site by drag-and-drop.

These methods for building web pages exist along a spectrum. At one end is the purely static HTML page. At the other end, you can build a web page entirely from code creating all of your HTML elements in the code-behind. Then there is the mushy ground in between where pages are a mix of static HTML intermingled with sections of script to build out any data-driven portions of the page. I am sure you have seen some classic ASP pages a lot of static text, interspersed with five, ten, or even more snippets of VBScript. Not a great design, but perhaps the best one could do with the technology available at the time.

How I Came to this Technique

Actually, my the first data-driven web site I ever built was a project for a web-programming class in 1995. This predated Java and VBScript. At that time you really had only the two end points of the spectrum. You could built pages as purely static HTML. But if you wanted any data driven component to the web page at all, you had to build the entire web page programmatically using cgi-bin programming (Perl was also an option). Unfortunately, programming cgi-bin was very cumbersome and a nightmare to debug.

My first commercial data-driven web project was written in classic ASP with VBScript using Microsoft's old Visual InterDev. Frankly, the result was a mess and barely worked. It was then ported to ASP.NET in C#. Being new to ASP.NET, the first iteration of the port was pretty much just recoding the script elements in C# without much change to the architecture. I am sure many of you have seen such ports, as I have on other projects written by other programmers. In the processing of the second iteration in ASP.NET, I found myself moving more and more code into the code-behind. I began building out my own library of ASP.NET classes and adopting more object-oriented techniques. For years, most of the work I did was Windows desktop applications in C++ and MFC so I was comfortable with object-oriented design and rich class libraries. On this and several other projects, I found that the more complicated the page logic, the better off it was in the code-behind. Finally, after working on this and several other projects, I decided to completely move all code to the code-behind for a new project. In other words, I moved my web page programming entirely to the end of the spectrum. As a result, I can build more robust data-driven web applications much faster than when I try to write HTML.

If all or even part of this story sounds familiar, you may want to consider this technique.

The Purpose of this Article

We have come a long way since cgi-bin. Using C# or VB.NET, it is now very easy to build your web pages entirely dynamically in the code behind. However, if your web programming skills evolved over the period of classic ASP, then you probably haven't thought much about this method of building web pages. Once you learn it, it is in fact a very easy technique and has some great benefits, but it requires a change in the way you think about web page programming.

The purpose of this article is to introduce you to the idea of building your data-driven web pages dynamically in the code behind. I will get you started on building a class library of your own to make this technique more efficient. I will show you how to build out pages dynamically. Finally, I will explain both the benefits and disadvantages.

Why You Should Read This Article

You should read this article if:

  1. You are planning a new data-driven web project and are looking for better techniques.
  2. You are trapped in a messy "classic ASP to ASP.NET port" and need some programming techniques to provide a most robust final application (I know there are many of you out there because I read the job postings).
  3. From an academic point of view, it will broaden your programming skills and improve your understanding of web page construction even if you don't adopt the strategy.
  4. Even if you are not interested in the pure code-behind approach, your should read the article because many web projects build out small portions of the page dynamically — if not the entire page — and you will want to understand the technique in case you get thrown into such a project.
  5. It could be a question on your next job interview.

Extending the .NET Web Classes

Building out your web pages dynamically in the code behind will not greatly simplify your web site development unless you have a rich library of code classes. The basic ASP.NET classes are impressive, but they are not enough. You will need to enhance them in your own library. If just try to do build your pages with the standard ASP.NET classes, you will never see the advantage of the method.

Building your own code library means:

  1. This method is less efficient for small projects, but becomes more efficient for larger projects.
  2. You can create a custom class library that can be shared among multiple projects making each new project quicker and easier to develop.

The project includes some example classes to get you started.

The TextWriter Class

We are building our web pages from code. That means no more typing HTML. In fact, we want to avoid typing HTML tags at all (or at least minimize it). Any HTML tags that you actually write should be in a class specifically designed to write HTML tags. This allows us to take advantage of the Visual Studio features such as auto-complete/intellisense and dynamic syntax checking. One such class is the TextWriter class.

Here is a portion of the class:

C#
public class TextWriter
{
    public TextWriter()

    {

    }

    static public string MakeParagraph(string s)
 
    {
        return "<p>" + s + "</p>";
     }
    static public string MakeLine(string s)
    {
        return s + "<br />";
    }

    static public string MakeH1Text(string s)
    {
        return "<h1>" + s + "</h1>";
     }
}

The purpose of the class is simply to write HTML formatted text. Note that all of the members are static. This is just a small sample of the types of functions that could be included in the text writer class. Anytime you find yourself writing an HTML tag outside of this class, perhaps it is time to add another function to the class.

In a code sample below, we will see this class in action.

The MyLiteral Class

A Literal control is simply a control that contains literal HTML markup. When the HTML for the page is generated, any text for the control is simply written out to the page — literally. When you build pages dynamically, you will use a lot of Literals. So it makes sense to derive your own Literal class as shown below. Note the use of a constructor to set the text value making programming the control more efficient. Also note the use of the TextWriter class.

C#
public class MyLiteral : Literal
{
    public MyLiteral(string strText)
    {
        Text = strText;
    }

    public void AddParagraph(string strText)
    {
        Text += TextWriter.MakeParagraph(strText);
    }
}

Admittedly, there is not much to this extended Literal class, although even this small class enhancement will save you a couple of lines of code for each use of the Literal. You will find yourself adding a lot of custom functionality to more complex web controls.

The MyPanel Class

In ASP.NET, Label controls produce text enclosed in <span> tags. Panel controls produce text enclosed in <div> tags. To make it easier to work with these controls and set their CSS styles, you should derive your own classes from these controls. Here is an example of your own custom Panel class.

C#
public class MyPanel : Panel
{
    public MyPanel(string strClass)
    {
        this.CssClass = strClass;
    }

    // Add a child panel to this panel
    public MyPanel AddDiv(string strClass)
    {
        MyPanel panel = new MyPanel(strClass);
        Controls.Add(panel);
        return panel;
    }

    // add a child panel to this panel
    public MyPanel AddDiv(string strClass, string strText)
    {
        MyPanel panel = AddDiv(strClass);
        panel.AddLiteral(strText);
        return panel;
    }


    // Add a literal control with text to this panel
    public Literal AddLiteral(string strText)
    {
        Literal lit = new Literal();
        lit.Text = strText;
        Controls.Add(lit);
        return lit;
    }


    // Add a label control with text to this panel
    public Label AddLabel(string strClass, string strText)
    {
        Label label = new Label();
        label.Text = strText;
        label.CssClass = strClass;
        Controls.Add(label);
        return label;
    }


    public void AddParagraph(string strText)
    {
        AddLiteral(TextWriter.MakeParagraph(strText));
    }

} // end of class declaration

Further Subclassing

To make this even more efficient, you may want to further subclass MyPanel. Perhaps you have a panel that displays a menu bar. You can create a class MenuPanel and add it to your pages wherever it is needed.

As a general rule, consider deriving your own subclasses from any of the System.Web.UI controls including tables, text boxes, check boxes, buttons, etc. For example, building a table programmatically can be tedious when you have to do it over and over because you must repeatedly set properties for each cell and row. Creating your own table class can make using tables much easier.

The "Base" Classes

Good object-oriented design means you are not writing the same code-snippets over and over. If you are, then that is a sign that there is something wrong with your class design. In any professional, large, data-driven web site, there is going to be some code that will be accessed by many pages. For example, error handling code is a commonly shared by many pages. Therefore, it is a good idea to create a BasePage class derived from System.Web.UI.Page. Then derive all of your web pages from BasePage.

You can do the same with master pages and user controls. This project includes BaseMasterPage for master pages and BaseUserControl for user controls.

Even if you do not know what to put in the base classes at the beginning of your project, you should follow this technique. By the end of your project, you may be surprised just how much code can be shared by each page.

The Pages and the PlaceHolder Control

So what do the pages look like with this programming technique? The have as little markup as possible. A simple page is shown below. The most important element — in fact the only control — is the PlaceHolder control. Every page has a single placeholder.

HTML
<%@ Page Language="C#" AutoEventWireup="true"  
   CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>This is a simple page example</title>

    <link rel="stylesheet" type="text/css" href="Css/StyleSharePoint.css">
   
</head>
<body>
    <form id="form1" runat="server">

    <div>
    <asp:PlaceHolder id="LocalPlaceHolder" runat="server"></asp:PlaceHolder>
    </div>
    </form>

</body>
</html>

All of the code in this file, with the exception of the placeholder, was generated automatically by Visual Studio.

In the code behind, the page is built out as controls added to the placeholder as shown below (note that the page is derived from BasePage):

C#
public partial class _Default : BasePage

{
    protected void Page_Load(object sender, EventArgs e)
    {
    Literal lit = new Literal();
     lit.Text = TextWriter.MakeH1Text("This is a sample page without a master page.");
     LocalPlaceHolder.Controls.Add(lit);

    lit = new Literal();
    lit.Text = TextWriter.MakeParagraph(
    "This sample project shows how to build out pages dynamically in the code behind.");
    LocalPlaceHolder.Controls.Add(lit);

    // in this case, "blockstyle" is the css style for my panel
    MyPanel panel = new MyPanel("blockstyle");
    panel.AddLiteral("This block of text shows how to build a panel.");
    LocalPlaceHolder.Controls.Add(panel);

    MyLabel label = new MyLabel("inlinestyle");
    label.AddParagraph("This is a label.");
    }

}

Note how we create each page element dynamically as a control and add it to the placeholder. The project includes samples to show how to do this with master pages and user controls as well.

Benefits to the Method

Great Support for Object Oriented Programming and Class Reuse — This is one of the strongest arguments for this method of web programming. Using classic ASP techniques, even with ASP.NET can result in a lot of repetition of the same code on multiple pages. As you move more and more of your page logic into classes called from the code-behind, you eliminate a lot of this redundant code. This reduces errors and makes large projects more manageable and robust.

Intellisense and real-time syntax checking make coding a snap — These Visual Studio features make writing code very easy, fast, and efficient. It really makes the difference for this style of programming. Without these technologies, the argument for this type of development would be much less compelling.

Best for data-driven web sites, such as catalogs pages that read from a database — This system works best for highly data-driven web projects where pages get much of their content from a database or other data source. Simply derive control classes for each type of data display — lists, forms, etc. Then build your page from these controls dynamically in the code-behind.

Best for pages where page design changes rapidly, such as from designers and management that can't decide what they want. — I worked on one project where top management could never decide on the final design for pages. They kept changing their minds. Single pages would be reworked five times or more. I found that building pages this way made it very easy to alter the appearance of each page with just a little code tweaking.

Easily Supports Cascading Style Sheets (CSS) — You may not think so at first, but once you get up and running with this method, you will find that it works very easily with CSS. As with the MyPanel class, simply requiring a CSS class style name as a constructor for your derived classes can simplify applying styles to your controls. Nested panel controls make it easy to cascade styles.

Management of Cookie and Session Variables — Well designed web applications have classes for handling cookies and session variables. This design makes it easier to access those classes from your controls.

Best for Pages with Highly Complex Logic — I found that this technique works best on pages with very complex logic — for example, a shopping cart, or a login page that must handle session variables or cookies. One some projects, I have been able to take pages that never worked quite right and fix them by adopting this programming technique. If your project has complex pages where you just can't seem to get rid of all of the bugs, try adopting this technique and see if it doesn't fix the problems.

Disadvantages

You Lose the Toolbox — Those of you who like dragging and dropping controls from the Visual Studio toolbox onto their web pages may not like this method of web development. However, you can still use the technique with user controls as shown in the example project.

Sparse Documentation — Much of the MSDN documentation for ASP.NET assumes that you will be dropping controls onto page files and setting their properties in the tags. It can be difficult to look at those examples and figure out how to do the same thing programmatically. This is also true for many code snippets that you find on web sites like this one and others popular for ASP.NET development. This was particularly a problem with AJAX controls. It took me awhile to get AJAX controls working using this method because I couldn't find examples that illustrated AJAX controls built programmatically. But once I figured out the basic principles, I was off and running.

Worst for "brochure" style web pages with lots of content that does not change — Just as this technique works best for highly data-driven web pages that feed from a database, it is least suitable for highly static web pages such as brochure-type web sites or simple data web sites where simply plopping a data grid on the page and connecting to a data source is sufficient. However, if I was to start a new project of that type, I would still consider using this technique.

Less efficient for small, one-off projects — As discussed, this technique becomes more efficient as your project gets larger. This is because building your own class library is important to the efficiency of the method. But remember that small projects often turn into large ones.

The Project

The included project shows how to use this technique to build out some simple pages. It shows with technique both with and without master pages, and also how you can use the technique with user controls. The project is in C# for Visual Studio 2005. However, the same principles can be applied in VB.NET.

Conclusions

The transition of web development from static HTML, to classic ASP, to ASP.NET has made it easier to move more and more of your page display logic into the code-behind and well-designed class objects. This article takes a look at the extreme end of the spectrum — moving all coding logic into the code-behind for all pages.

As with any extreme method of programming, I expect that there will be resistance to adopting it in its entirety for your next project. However, you can take these techniques and incorporate them gradually into your projects — especially page rewrites. Central to the technique is building up a library of classes which you can reuse. I think you will find that as your class library grows, you will find it easier to adopt the technique and quickly build complex and robust web projects. I have used this technique very successfully in several projects, with almost all page presentation logic in the code-behind.

If you are working on a web project that is a "web" of messy classic ASP pages that you are trying to port to ASP.NET, I strongly recommend that you consider moving your project to this development method. It isn't something you would do in one iteration, but rather, with each iteration, move more and more of the code to code behind Use object-oriented techniques to build out a class library. Within several iterations, you will have a robust, well-designed, and very manageable project.

For me, adopting this technique required a change in mindset, undoing years of conditioning about web development. It is impossible to convey all aspects of the technique in a single article. I could fill a book on the technique. But check out the project and give the method some consideration. When you come across a web programming challenge, think about how you would solve it using this technique instead of the way you typically approach web programming. Over time, you may too find yourself programming more robust sites in less time.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
President Starpoint Software Inc.
United States United States
Bob Pittenger is founder and President of Starpoint Software Inc. He holds a B.A. degree from Miami University, M.S. and Ph.D. degrees from Purdue University, and an MBA from Xavier University. He has been programming since 1993, starting with Windows application development in C++/MFC and moving to C# and .NET around 2005 and is a .NET Microsoft Certified Professional Developer.

Bob is the author of two books:
Billionaire: How the Ultra-Rich Built Their Fortunes Through Good and Evil and What You Can Learn from Them
and
Wealthonomics: The Most Important Economic and Financial Concepts that Can Make You Rich Fast.
Visit http://www.billionairebook.net for more information.

Comments and Discussions

 
QuestionHow does one wire up gridview functionality, like sorting and paging from the code behind? Pin
dgiragosian1-Mar-12 5:10
dgiragosian1-Mar-12 5:10 
GeneralSome options Pin
Ricky Wang13-May-08 23:46
Ricky Wang13-May-08 23:46 
GeneralYes,but what if.... Pin
tsimikkonen7-May-08 1:36
tsimikkonen7-May-08 1:36 
GeneralI agree, but extend further Pin
CodePuller1-May-08 13:44
CodePuller1-May-08 13:44 
GeneralYou should look at StringTemplate Pin
ncarey28-Apr-08 7:54
ncarey28-Apr-08 7:54 
GeneralRe: You should look at StringTemplate Pin
dcbrower6-May-08 8:15
dcbrower6-May-08 8:15 
GeneralRe: You should look at StringTemplate Pin
ncarey6-May-08 9:53
ncarey6-May-08 9:53 
GeneralRe: You should look at StringTemplate Pin
jamison77713-Feb-09 9:27
jamison77713-Feb-09 9:27 
GeneralCustom Controls Pin
stixoffire27-Apr-08 22:15
stixoffire27-Apr-08 22:15 
GeneralI disagree Pin
Nicholas Butler26-Apr-08 1:04
sitebuilderNicholas Butler26-Apr-08 1:04 
GeneralRe: I disagree with disagreeing Pin
Fred Pinto26-Apr-08 2:43
Fred Pinto26-Apr-08 2:43 
GeneralRe: I disagree with disagreeing - The truth is out there Pin
Dewey26-Apr-08 23:30
Dewey26-Apr-08 23:30 
GeneralRe: I disagree with disagreeing - The truth is out there Pin
dcbrower6-May-08 8:19
dcbrower6-May-08 8:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.