Tuesday, 17 February 2015

Creating web pages dynamically in the Code Behind in ASP.Net using C# and VB.Net


In this article I will explain how to create dynamic web pages in ASP.Net code behind using C# and VB.Net.
 
 
Concept
There are other articles creating ASPX pages dynamically by generating an .ASPX file, in contrast my approach is clean and makes use of database to allow users manage and control the dynamic pages with ease.
Each page is given a unique name and is saved in database and then with the help URL Routing feature the same is accessed dynamically.
 
 
Database
Below is the schema of the Table that will be used for this article. It will be used to store the name of the page, its Title and the Content.
Create dynamic ASPX page in ASP.Net
 
Note: The SQL for creating the database is provided in the attached sample code.
 
 
Namespaces
The following namespaces will be used on all the pages used for this article.
C#
using System.Data;
using System.Configuration;
using System.Data.SqlClient;
 
VB.Net
Imports System.Data
Imports System.Configuration
Imports System.Data.SqlClient
 
 
 
Creating Dynamic Pages
In order to create and save the dynamic pages, I have made use of a page named AddPage.aspx.
HTML Markup
The following HTML Markup consists of an HTML form to allow user save the details of the dynamic page such as its Name, Title and Content. The Content TextBox is a Multiline TextBox and I have made it a Rich TextBox using TinyMCE RichTextEditor plugin.
<table border="0" cellpadding="0" cellspacing="0">
<tr>
    <td>
        Name:
    </td>
</tr>
<tr>
    <td>
        <asp:TextBox ID="txtPageName" runat="server" />
    </td>
</tr>
<tr>
    <td>
        &nbsp;
    </td>
</tr>
<tr>
    <td>
        Title:
    </td>
</tr>
<tr>
    <td>
        <asp:TextBox ID="txtTitle" runat="server" />
    </td>
</tr>
<tr>
    <td>
        &nbsp;
    </td>
</tr>
<tr>
    <td>
        Content:
    </td>
</tr>
<tr>
    <td>
        <asp:TextBox ID="txtContent" runat="server" TextMode="MultiLine" />
    </td>
</tr>
<tr>
    <td>
        &nbsp;
    </td>
</tr>
<tr>
    <td>
        <asp:Button ID="btnSubmit" Text="Submit" runat="server" OnClick="Submit" />
    </td>
</tr>
</table>
<script type="text/javascript" src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>
<script type="text/javascript">
tinymce.init({ selector: 'textarea' });
</script>
 
Code
The following event handler is used to save the details of the page to the database table. I have replaced the spaces in the name of the page with dashes so that it looks neat in the URL. Similarly you can also remove other special characters.
C#
protected void Submit(object sender, EventArgs e)
{
    string query = "INSERT INTO [Pages] VALUES (@PageName, @Title, @Content)";
    string conString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
    using (SqlConnection con = new SqlConnection(conString))
    {
        using (SqlCommand cmd = new SqlCommand(query, con))
        {
            cmd.Parameters.AddWithValue("@PageName", txtPageName.Text.Replace(" ""-"));
            cmd.Parameters.AddWithValue("@Title", txtTitle.Text);
            cmd.Parameters.AddWithValue("@Content", txtContent.Text);
            con.Open();
            cmd.ExecuteNonQuery();
            con.Close();
            Response.Redirect("~/Default.aspx");
        }
    }
}
 
VB.Net
Protected Sub Submit(sender As Object, e As EventArgs)
    Dim query As String = "INSERT INTO [Pages] VALUES (@PageName, @Title, @Content)"
    Dim conString As String = ConfigurationManager.ConnectionStrings("constr").ConnectionString
    Using con As New SqlConnection(conString)
        Using cmd As New SqlCommand(query, con)
            cmd.Parameters.AddWithValue("@PageName", txtPageName.Text.Replace(" ""-"))
            cmd.Parameters.AddWithValue("@Title", txtTitle.Text)
            cmd.Parameters.AddWithValue("@Content", txtContent.Text)
            con.Open()
            cmd.ExecuteNonQuery()
            con.Close()
            Response.Redirect("~/Default.aspx")
        End Using
    End Using
End Sub
 
 
URL Routing Implementation
Once the dynamic pages are created, the next task is to implement URL Routing so that we can access the dynamic pages through the browser.
Thus now you need to add a Global.asax file and in that you need to register the Route which sends the requests to a page named DynamicPage.aspx (explained later).
C#
<%@ Application Language="C#" %>
<%@ Import Namespace="System.Web.Routing" %>
<script runat="server">
    void Application_Start(object sender, EventArgs e)
    {
        RegisterRoutes(RouteTable.Routes);
    }
   
    static void RegisterRoutes(RouteCollection routes)
    {
        routes.MapPageRoute("DynamicPage""Pages/{PageName}.aspx""~/DynamicPage.aspx");
    }
</script>
 
VB.Net
<%@ Application Language="VB" %>
<%@ Import Namespace="System.Web.Routing" %>
<script RunAt="server">
    Private Sub Application_Start(sender As Object, e As EventArgs)
        RegisterRoutes(RouteTable.Routes)
    End Sub
 
    Private Shared Sub RegisterRoutes(routes As RouteCollection)
       routes.MapPageRoute("DynamicPage""Pages/{PageName}.aspx""~/DynamicPage.aspx")
    End Sub
</script>
 
Note: URL Routing is available only in .Net 3.5 SP1 and higher frameworks. If you are unable to understand this concept, please refer my article Implement URL routing in ASP.Net Web Forms.
 
 
Rendering the Dynamic Page from database
For displaying dynamic pages I have created a page named DynamicPage.aspx.
HTML Markup
The HTML Markup consists of Labels to display the Title and Content of the dynamic page.
<h2><asp:Label ID="lblTitle" runat="server" /></h2>
<hr />
<asp:Label ID="lblContent" runat="server" />
 
Code
Inside the Page Load event handler, the name of the Dynamic Page is fetched from the RouteData values.
Then using the name of the Page its details such as Title and Content are fetched from the database and displayed using Label controls.
C#
protected void Page_Load(object sender, EventArgs e)
{
    if (!this.IsPostBack)
    {
        this.PopulatePage();
    }
}
 
private void PopulatePage()
{
    string pageName = this.Page.RouteData.Values["PageName"].ToString();
    string query = "SELECT [Title], [Content] FROM [Pages] WHERE [PageName] = @PageName";
    string conString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
    using (SqlConnection con = new SqlConnection(conString))
    {
        using (SqlCommand cmd = new SqlCommand(query))
        {
            using (SqlDataAdapter sda = new SqlDataAdapter())
            {
                cmd.Parameters.AddWithValue("@PageName", pageName);
                cmd.Connection = con;
                sda.SelectCommand = cmd;
                using (DataTable dt = new DataTable())
                {
                    sda.Fill(dt);
                    lblTitle.Text = dt.Rows[0]["Title"].ToString();
                    lblContent.Text = dt.Rows[0]["Content"].ToString();
                }
            }
        }
    }
}
 
VB.Net
Protected Sub Page_Load(sender As Object, e As EventArgsHandles Me.Load
    If Not Me.IsPostBack Then
        Me.PopulatePage()
    End If
End Sub
 
Private Sub PopulatePage()
    Dim pageName As String = Me.Page.RouteData.Values("PageName").ToString()
    Dim query As String = "SELECT [Title], [Content] FROM [Pages] WHERE [PageName] = @PageName"
    Dim conString As String = ConfigurationManager.ConnectionStrings("constr").ConnectionString
    Using con As New SqlConnection(conString)
        Using cmd As New SqlCommand(query)
            Using sda As New SqlDataAdapter()
                cmd.Parameters.AddWithValue("@PageName", pageName)
                cmd.Connection = con
                sda.SelectCommand = cmd
                Using dt As New DataTable()
                    sda.Fill(dt)
                    lblTitle.Text = dt.Rows(0)("Title").ToString()
                    lblContent.Text = dt.Rows(0)("Content").ToString()
                End Using
            End Using
        End Using
    End Using
End Sub
 
 
Displaying the List of Dynamic Pages
Once the page details are inserted in database, the AddPage.aspx page redirects the user to Default.aspx where user can view all the dynamic pages saved in the database.
 
HTML Markup
The HTML Markup consists of a HyperLink to allow user access the AddPage.aspx and a Repeater control to display the list of the dynamic pages present in the database.
You will notice that the NavigateUrl of the HyperLink has a URL similar to that of the Route registered earlier in the Global.asax file.
<asp:HyperLink ID="HyperLink1" NavigateUrl="~/AddPage.aspx" Text="Add Page" runat="server" />
<hr />
<asp:Repeater ID="rptPages" runat="server">
<ItemTemplate>
    <%# Container.ItemIndex + 1 %>
    <asp:HyperLink ID="HyperLink2" NavigateUrl='<%# Eval("PageName", "~/Pages/{0}.aspx") %>' Text='<%# Eval("Title") %>'
        runat="server" />
</ItemTemplate>
<SeparatorTemplate>
    <br />
</SeparatorTemplate>
</asp:Repeater>
 
Code
The Repeater control is populated with the dynamic pages saved in the database table in the Page Load event.
C#
protected void Page_Load(object sender, EventArgs e)
{
    if (!this.IsPostBack)
    {
        this.PopulatePage();
    }
}
 
private void PopulatePage()
{
    string pageName = this.Page.RouteData.Values["PageName"].ToString();
    string query = "SELECT [Title], [Content] FROM [Pages] WHERE [PageName] = @PageName";
    string conString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
    using (SqlConnection con = new SqlConnection(conString))
    {
        using (SqlCommand cmd = new SqlCommand(query))
        {
            using (SqlDataAdapter sda = new SqlDataAdapter())
            {
                cmd.Parameters.AddWithValue("@PageName", pageName);
                cmd.Connection = con;
                sda.SelectCommand = cmd;
                using (DataTable dt = new DataTable())
                {
                    sda.Fill(dt);
                    lblTitle.Text = dt.Rows[0]["Title"].ToString();
                    lblContent.Text = dt.Rows[0]["Content"].ToString();
                }
            }
        }
    }
}
 
VB.Net
Protected Sub Page_Load(sender As Object, e As EventArgsHandles Me.Load
    If Not Me.IsPostBack Then
        Me.BindPages()
    End If
End Sub
 
Private Sub BindPages()
    Dim query As String = "SELECT [PageName], [Title], [Content] FROM [Pages]"
    Dim conString As String = ConfigurationManager.ConnectionStrings("constr").ConnectionString
    Using con As New SqlConnection(conString)
        Using cmd As New SqlCommand(query)
            Using sda As New SqlDataAdapter()
                cmd.Connection = con
                sda.SelectCommand = cmd
                Using dt As New DataTable()
                    sda.Fill(dt)
                    rptPages.DataSource = dt
                    rptPages.DataBind()
                End Using
            End Using
        End Using
    End Using
End Sub
 
 
 
Demo
Create dynamic ASPX page in ASP.Net
 
 
Errors
The following errors you might encounter while implementing the dynamic pages.
Create dynamic ASPX page in ASP.Net
The above error will occur when you have not implemented the Routing properly and trying to access the dynamic pages.
 
Create dynamic ASPX page in ASP.Net
The above error occurs when ASP.Net detects HTML content posted to the server and hence to solve this error please refer my article ASP.Net Error: A potentially dangerous Request.Form value was detected from the client.
 

No comments:

Post a Comment