AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=711&pId=-1
Preventing Duplicate Record Insertion on Page Refresh or Postback of a Web Form
page
by Jeremy Schell
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 24911/ 14

Introduction

One of the biggest challenges for Internet developers is the resubmission of form data or the refresh of a form to post information to a database. This happens when the user, for whatever reason, resubmits or refreshes the form, which has the potential to cause chaos with duplicated database insertions or repeated email submissions. There have been a number of theories presented on how to deal with the problem; one of the most thorough I’ve read being from Terri Morton and located at www.aspalliance.com/687. It is not my intent to dispute which of these methods is the best, but instead to offer an alternative approach.

History

Several years ago I was challenged by a company that was performing online contest submissions to limit users to one submission per “typed” entry. Additionally, they wanted to prevent mass submission companies from flooding their contest with unprospected candidates and automated entries. After looking at many options, I decided to create a single-use formKey that I could assign and track at the server level for each user every time a form was loaded. Once the form was submitted, I would confirm the existence of the formKey for that form and allow the submission to be processed. At that point the key would be purged from the system and could no longer be used. Then, if the user hit the browser's Refresh button or tried to repost the submission, I could handle the repost in any manner knowing it was a repeat submission. In cases where a developer is using a multi-step form on a single web page, this process can be integrated easily to maintain each step of the form submission process. To expand upon our solution, we’ve integrated it into an ASP.NET server control that can easily be dragged onto a web form in Visual Studio and then attached from the code behind to authenticate the postback as a single submission, making it easy for any developer to integrate.

The Process

The overall process works as follows.

  1. During initial page load, register the web form and generate a unique formKey, e.g., “A”.
  2. Once the page is completed and a postback is performed, formKey “A” exists within the POST form collection. We authenticate this formKey against the database for the web form to confirm it is valid. Once confirmed, the page processing is allowed to continue and the formKey is deleted. If the user presses the browser's Refresh button, or presses the Back button and then reposts the data, formKey “A” will again be contained within the POST form collection and will no longer authenticate within the database.
  3. Simultaneously, a new formKey “B” is generated for the next possible postback and formKey “A” will no longer function. This is necessary for multiple-step forms, and upon postback formKey “B” can be properly authenticated.
  4. This process repeats itself each time the screen is refreshed or a postback is performed.

Because this solution required the use of a database, we also wanted the solution to be scalable to all of our clients and their forms, so we updated the database and server control to allow a single control to manage multiple sites and multiple forms on each site. As each site and form is called, the server control registers the web site and web form within the database for future use and tracking.

Implementation

All formKeys are created by the server control and then registered with the database for use on each form requested by the user. The database consists of three tables: Sites, Forms, and FormKeys. Each record within the Sites table maintains a unique hostname where forms are submitted from. Similarly, the Forms table maintains each URL where a form is submitted from. Finally, the FormKeys table tracks each formKey provided by the server control, the user’s IP address, and the specific Site and Form in which the key is valid. This is all passed through the stored procedure “spInsertFormKey” when the form is originally requested. Currently the FormValidator maintains keys for one day but the system can easily be configured from the stored procedure “spAuthenticateFormKey” to enforce a shorter life cycle for each key.

Upon each postback the code calls the ValidatePostback function which provides a Boolean response indicating whether the formKey provided on the form was valid for the current submission location. If false, either the form is a repeat submission or it was an automated submission from some other source. When the ValidatePostback function is called, the server control calls the “spAuthenticateFormKey” procedure providing the user’s IP, the formKey as found in the form collection, the hostname, and the filename of the form. This is compared against previous submissions. If a match is found a successful response is sent to the server control and the previous formKey is removed from the database.

Usage of the server control is extremely simple. Add the following four keys to your web.config file with the appropriate database connection string information.

Listing 1 – Web.Config Changes

<add key="FV_dsn_Server" value="[SERVER NAME OR IP]"/>
<add key="FV_dsn_Database" value="FormManager"/>
<add key="FV_dsn_Username" value="[USERNAME TO CONNECT TO SQL SERVER]"/>
<add key="FV_dsn_Password" value="[PASSWORD TO CONNECT TO SQL SERVER]"/>

You can also add to the web.config file a key named FV_EnforceValidation and set its value to False, which will disable all form validation on a site so that you can test submit/resubmit behavior without having to register a formKey. Be sure to either remove this key or set its value to True once you have finished testing, or it will not protect against duplicate submissions.

When your code handles a postback, just wrap your actual processing within the following code:

Listing 2 – Postback Validation

Dim validator As New TectonicConcepts.FormValidator.FormValidator
If validator.ValidatePostback = True Then
    ' Do something with the form
EndIf

If you have code to perform a redirection, display a thank you message, or proceed to the next step in a multi-form page, you’ll want to place that code outside of this validator block. For example, on our contact form we do the following: on the first postback we send an email, but on a subsequent refresh or a postback that is not valid, we don’t send an email but still display the thank you message.

Listing 3 – Sample Postback with Validation

Private Sub Submit_Click(sender As Object, e As EventArgs)
    If Page.IsValid Then
        Dim validator As New TectonicConcepts.FormValidator.FormValidator
        If validator.ValidatePostback = True Then
            Message.Text = "Form data is new, and will be processed"
        Else
            Message.Text = "Form data is a resubmission, and will not be processed"
        End If
    Else
        Message.Text = "Form data is not valid, and will not be processed"
    End If
End Sub

Conclusion

If you download the FormValidator server control and its accompanying database setup script, you will have an easy way to check whether the page has been refreshed or the form resubmitted. You can perform this check before performing sensitive actions, such as making a database insertion or sending an email. It couldn't be easier.


Product Spotlight
Product Spotlight 

©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-26 3:20:26 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search