In this article I will explain with an example, how to implement Single File Page (ASPX) Model in ASP.Net using C# and VB.Net.
In Single File Page (ASPX) Model, only one ASPX Page is used to create multiple dynamic pages with unique content and URL.
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.
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>
</td>
</tr>
<tr>
<td>
Title:
</td>
</tr>
<tr>
<td>
<asp:TextBox ID="txtTitle" runat="server" />
</td>
</tr>
<tr>
<td>
</td>
</tr>
<tr>
<td>
Content:
</td>
</tr>
<tr>
<td>
<asp:TextBox ID="txtContent" runat="server" TextMode="MultiLine" />
</td>
</tr>
<tr>
<td>
</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>
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 EventArgs) Handles 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 EventArgs) Handles 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
Errors
The following errors you might encounter while implementing the dynamic pages.
The above error will occur when you have not implemented the Routing properly and trying to access the dynamic pages.
Downloads