Saving and Retrieving Web Page Control with SQL Server and C#


Introduction

This article describes a simple approach to storing, retrieving, and redisplaying web pages.  Such might be useful if you need to store exact copies of confirmation pages (e.g., following a sales transaction) or something along those lines.  The example provided is in the form of a simple application that simulates a sales oriented web site; the example uses an SQL Server database and LINQ to SQL.  Pages are stored and retrieved from the database for redisplay in a web browser.


 
Figure 1:  Demo Website

Getting Started:

In order to get started, unzip the included project and save it to your hard drive.  Open the web application and examine the contents in the solution explorer.

Figure 2:  Solution Explorer

The solution contains a single web application project called "DangerousPets".  This web application contains three web pages (default, order, and review) along with a single master page; all code behind is in VB.  The default web page is used to display a simulation or an ordering system, the order web page is used to display a simulation of an order confirmation, and the review page is used to display retrieved web pages.  The app code folder contains a DBML file supporting the LINQ to SQL interface to the database.

The bulk of the code is there just to provide a simple framework for creating something to save and restore for redisplay.  The relevant parts of the code used to actually store and recall the order page will be pointed out in the following sections. 

Code:  Default.aspx

The default page is used to create an order so that we have something to save to the database.  It is a nonsense web page that badly simulates an online ordering system for a fake company called, "Dangerous Pets".  The purpose of the page is to allow the user to review product descriptions and enter a count for the number of items that the user wishes to order at the given price.  This information is used to generate an order confirmation and it is the order confirmation that is persisted to the database.

There is nothing particularly interesting about the page's markup; it contains little more than a table used to display a fictitious catalog of scary pets available for sale.  You may open the page from the attached demonstration project if you'd like to review its content; it won't include it here as it is not important to the issue of this article.

Code:  Default.cs

The code behind for the default page it equally uninspiring; it contains only a single button click event handler used to complete a phony order by pushing any order values captured from the default page into session variables and then redirecting the user to the order page.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls; 

 

public partial class _Default : System.Web.UI.Page

{

 

    protected void Page_Load(object sender, EventArgs e)

    {

        // nothing added

    } 

 

    protected void btnSubmitOrder_Click(object sender, EventArgs e)

    {

        // alligators

        if (!String.IsNullOrEmpty(txtAlligators.Text))

            System.Web.HttpContext.Current.Session["Alligators"] =

            txtAlligators.Text;

 

        // Banana Slugs

        if (!String.IsNullOrEmpty(txtBananaSlugs.Text))

            System.Web.HttpContext.Current.Session["BananaSlugs"] =  

            txtBananaSlugs.Text;

 

        // Black Widows

        if (!String.IsNullOrEmpty(txtBlackWidows.Text))

            System.Web.HttpContext.Current.Session["BlackWidows"] =

            txtBlackWidows.Text;

 

        // Fugu

        if (!String.IsNullOrEmpty(txtFugu.Text))

            System.Web.HttpContext.Current.Session["Fugu"] = txtFugu.Text;

 

        // Rattlesnakes

        if (!String.IsNullOrEmpty(txtRattlesnakes.Text))

            System.Web.HttpContext.Current.Session["Rattlesnakes"] =

            txtRattlesnakes.Text;

 

        // Scorpions

        if (!String.IsNullOrEmpty(txtScorpions.Text))

            System.Web.HttpContext.Current.Session["Scorpions"] =

            txtScorpions.Text;

 

        // Venus Fly Traps

        if (!String.IsNullOrEmpty(txtVenusFlyTraps.Text))

            System.Web.HttpContext.Current.Session["VenusFlyTraps"] =

            txtVenusFlyTraps.Text;

 

        Response.Redirect("Order.aspx");

    }
}

 

Code:  Order.aspx

 

The order page is used to display a phony order confirmation page.  There is nothing particularly interesting about it; it merely displays the counts for each item ordered along with a price total.  Again, you can review the content of the page from the attached project.

Code:  Order.cs

The form class contains the code used to save the page to an SQL Server database.  This class begins with the declaration of some variables used to display the order information on the order page:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls; 

 

public partial class Order : System.Web.UI.Page

{

       

    // Variable Declarations

 

    // counts for products

    protected int alligatorCount;

    protected int bananaSlugCount;

    protected int blackWidowsCount;

    protected int fuguCount;

    protected int rattlesnakeCount;

    protected int scorpionCount;

    protected int venusFlyTrapsCount;

 

    // subtotals for each quantity of

    // ordered items

    protected double alligatorAmount;

    protected double bananaSlugAmount;

    protected double blackWidowsAmount;

    protected double fuguAmount;

    protected double rattlesnakeAmount;

    protected double scorpionAmount;

    protected double venusFlyTrapsAmount;

 

    // sums for both quantity and amount

    protected int totalCount;

    protected double totalAmount; 

 

    protected void Page_Load(object sender, EventArgs e)

    {

        // Alligator count and total

        try

        {

            alligatorCount =

Convert.ToInt32(

System.Web.HttpContext.Current.Session["Alligators"]);

        }

        catch

        {

            alligatorCount = 0;

        }

        // Total

        alligatorAmount = alligatorCount * 22.15;

 

 

        // Banana Slug count and total

        try

        {

            bananaSlugCount =

Convert.ToInt32(

System.Web.HttpContext.Current.Session["BananaSlugs"]);

        }

        catch

        {

            bananaSlugCount = 0;

        }

        // Total

        bananaSlugAmount = bananaSlugCount * 1.25;

 

 

        // Black Widows

        try

        {

            blackWidowsCount =

Convert.ToInt32(

System.Web.HttpContext.Current.Session["BlackWidows"]);

        }

        catch

        {

            blackWidowsCount = 0;

        }

        // Total

        blackWidowsAmount = blackWidowsCount * 2.99;

 

        // Fugu

        try

        {

            fuguCount =

Convert.ToInt32(

System.Web.HttpContext.Current.Session["Fugu"]);

        }

        catch

        {

            fuguCount = 0;

        }

        // Total

        fuguAmount = fuguCount * 9.0;

 

        // Rattlesnake

        try

        {

            rattlesnakeCount =

Convert.ToInt32(

System.Web.HttpContext.Current.Session["Rattlesnakes"]);

        }

        catch

        {

            rattlesnakeCount = 0;

        }

        // Total

        rattlesnakeAmount = rattlesnakeCount * 12.77;

 

        // Scorpions

        try

        {

            scorpionCount =

Convert.ToInt32(

System.Web.HttpContext.Current.Session["Scorpions"]);

        }

        catch

        {

            scorpionCount = 0;

        }

        // Total

        scorpionAmount = scorpionCount * 1.55;

 

        // Venus Fly Traps

         try

        {

            venusFlyTrapsCount =

Convert.ToInt32(

System.Web.HttpContext.Current.Session["VenusFlyTraps"]);

        }

        catch

        {

            venusFlyTrapsCount = 0;

        }

        // Total

        venusFlyTrapsAmount = venusFlyTrapsCount * 3.25;

 

        // the total count of all products ordered

        totalCount = alligatorCount + bananaSlugCount

        + blackWidowsCount + fuguCount + rattlesnakeCount +

        scorpionCount + venusFlyTrapsCount;

 

        totalAmount = alligatorAmount + bananaSlugAmount +

        blackWidowsAmount + fuguAmount + rattlesnakeAmount +

        scorpionAmount + venusFlyTrapsAmount;

After setting the variables, the next part of the load event handler checks to see if anything was ordered and then building a record; in this case the record only requires an ID (as a GUID) and the content containing the page's HTML.  The Page.RenderControl method is used to populate the html text writer with the page content; this is then converted to a byte array which is subsequently stored in the database along with the order ID using LINQ to SQL.

        // if the user orders at least one product, save

        // the order to the database.

        if (totalCount > 1)

 

            // save html to database

            try

            {

                // create ID for the record

                Guid savedConfirmId;

                savedConfirmId = Guid.NewGuid();

 

                // get the html converted to a byte array

                System.IO.StringWriter stringWriter = new

                System.IO.StringWriter();

 

                System.Web.UI.HtmlTextWriter htmlWriter = new

    System.Web.UI.HtmlTextWriter(stringWriter);

 

                Page.RenderControl(htmlWriter);

                htmlWriter.Flush();

 

                String str = stringWriter.ToString();

                Byte[] bArr = System.Text.Encoding.UTF8.GetBytes(str);

 

                // Create a new saved order object (LINQ to SQL)

                // and populate the ID and content fields

                saved_order so = new saved_order();

                so.ID = Guid.NewGuid();

                so.Content = bArr;

 

                // Get an instance of the data context and

                // try to submit the new order for storage

                WsdalDataContext context = new WsdalDataContext();

                context.saved_orders.InsertOnSubmit(so);

                context.SubmitChanges();

            }

            catch(Exception ex)

            {

                // if any errors occur, display them

                Response.Write(ex.ToString());

 

            }

 

        }

}

Code:  Review.aspx

The form class contains a single literal control used to display an order retrieved from the database.   You can review the page content in the attached project if so desired.

Code:  Review.cs

This form class is used to display a stored order confirmation page; the execution is straightforward in the example; the order ID is passed in the query string and used in a LINQ to SQL call to recover the page content associated with the order ID from the database.  The content, stored as a byte array, is converted to a string which is then passed to the literal control used to display the stored page.  The entire class is as follows:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls; 

 

public partial class Review : System.Web.UI.Page

{

 

    /// <summary>

    /// Display the order retrieved from the

    /// database

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="e"></param>

    protected void Page_Load(object sender, EventArgs e)

    {

        // get the order id from the query string

        String strId = Request.QueryString["orderId"];

        WsdalDataContext context = new WsdalDataContext();

 

        // Retrieve the page content from the database (binary)

        var pageContent = (from a in context.GetTable<saved_order>()

                          where a.ID.ToString() == strId

                          select a.Content).First();

 

        // display the order confirmation after converting

        // the binary back to a string containing the original HTML

        string htmlPageContent =

            ConvertBinaryToString(pageContent.ToArray());

 

        // display the retrieved page in a literal cotnrol

        litPage.Text = htmlPageContent;

    } 

 

    /// <summary>

    /// Conver the byte arra to text (html) for

    /// display

    /// </summary>

    /// <param name="input"></param>

    /// <returns></returns>

    protected string ConvertBinaryToString(Byte[] input)

    {

        System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();

        String str = enc.GetString(input);

        return str;

    }

}

Code:  MasterPage.master

The master page contains a simple banner along with a drop down list used to display existing order IDs.  A button adjacent to the drop down list is used to redirect the page to the review page and to format the query string containing the order ID used by the review page to recover and display the stored order page.
You may review the markup from the attached project.

Code:  MasterPage.master.cs

The code behind for the master page contains the code used to generate a list of orders which are used to populate a drop down list.  That list is used to define which order to recover and redisplay.  An image button's click event handler is used to redirect the user to the review page; the currently selected order from the drop down list is used to format a query string which is in turn used in the review page to determine which order to recover and display.  The code is annotated and easy to follow:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls; 

 

public partial class MasterPage : System.Web.UI.MasterPage

{

 

    /// <summary>

    /// Reload the list of completed sales orders

    /// on page load

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="e"></param>

    protected void Page_Load(object sender, EventArgs e)

    {

        if (!Page.IsPostBack)

        {

            UpdateList();

        }

    } 

 

    /// <summary>

    /// Redirect user to review page and pass order ID

    /// in query string

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="e"></param>

    protected void imgRetrieveOrder_Click(object sender,

ImageClickEventArgs e)

    {

        try

        {

            Response.Redirect("Review.aspx?orderId=" +

ddlOrderList.SelectedItem.Text);

        }

        catch { }

    } 

 

    /// <summary>

    /// Update the list of completed sales order

    /// to populate the drop down list

    /// </summary>

    protected void UpdateList()

    {

        WsdalDataContext context = new WsdalDataContext();

        var orders = (from a in context.GetTable<saved_order>()

                        select a.ID).ToList();

 

        ddlOrderList.Items.Clear();

        ddlOrderList.DataSource = orders;

        ddlOrderList.DataMember = ID;

        ddlOrderList.DataBind();

    }

 

}

Code:  Wsdal.dbml

The DBML maintains a connection to the WebStore database; the visual designer contains only the saved orders table.  You can review this in the project if you'd like but that is all there is to it.

Database

The database used for this demonstration contains only a single table containing only two fields, ID and content.  If you decide to run the demonstration project, create a database called "WebStore" and a single table (saved_orders) with the following fields and update the project connection string to point to that database.


 
Figure 3.  Saved Orders Table

Summary

The article addresses a simple process for capturing a displayed webpage and persisting that page to a database.  Further, the article addresses the recovery and redisplay of web pages stored in this manner.  This approach might be useful to anyone that wants to store an exact copy of a page as it was displayed to a user, for example, an order confirmation.

erver'>

Recommended Free Ebook
Similar Articles