About Tectonics

Latest News

Our Services

Custom Web Site

.NET Products



Contact Us

geared up
  • MythicLeaders - CRM
  • HBAL Document Management
  • New Equity Mortgage CRM2005 Integration

      custom .net solutions

    Preventing Duplicate Record Insertion or Page Refresh on postback of a form
    by Jeremy Schell, Tectonic Concepts Chief Propeller Head

    As with many Internet developers one of the biggest challenges and end user frustrations is the resubmission of data or refresh of a form to post information to a database by an unaware user.  Quite often this happens and the user for what ever reason will resubmit or refresh the form and potentially cause ciaos with database and/or email submissions.  There have been a number of theories presented on this subject, one of the most thorough I’ve read being from Terri Morton, http://aspalliance.com/687.  It is not my intent to dispute which of these methods is best but instead to offer an alternative suggestion.

    Several years ago I was challenged by a company who 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 concluded 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 refresh or tried to repost the submission, I could handle the repost in any manner knowing it was a repeat submission.  In the cases when a developer is using a multi-step form on a single web form, this process can easily be integrated to maintain each “step” of the form submission process.  To expand upon our solution we’ve integrated it into a VS.NET toolbox server control that can easily be dragged onto a web form and then attached from the code behind to authenticate the postback as a single submission making it easy for any developer to integrate. 

    The overall process works as follows:

    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 done, formKey “A” exists within the POST Form Collection.  We authenticate this formKey against the database for the web form to confirm it is validate.  Once confirmed the page processing is allowed to continue and the formKey is deleted.  If the user presses REFRESH within the browser or their back button and repost 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 initiated.

    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.

    All formKeys are created by the server control and then registered with the database for use on each user requested form.  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, user’s IP address, and specific Site and Form in which the key is valid.  This is all passed through the stored procedure “spInsertFormKeymKey” 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 developer calls the ValidatePostback function which provides a Boolean response (true/false) of whether the formKey provided on the form was valid or not 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, formKey as found in the POST/GET collection, hostname and file name of the form.  This is compared against previous submissions.  If one matches a successful response is sent to the server control and the previous formKey removed from the database.

    Usage of the server control is extremely simple, add the server control to your VS.NET or WebMatrix toolbox and drag the control onto your web form.  For best implementation, place it between the FORM tags but outside any possible hidden panels, tables or other components that may change throughout the lifecycle of your form.  Next, add the following four keys to your web.config with the appropriate connection string information to your database.

                <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 the following key FV_EnforceValidation to the web.config and set to False to disable all form validation on a site for your testing purposes so you can submit/resubmit without having to register a formKey.  Be sure to either remove this key or set to True once you are done testing or it will not protect against duplicate submissions.

    When you do a postback just wrap your actual processing within the following code:

    Dim validator As New TectonicConcepts.FormValidator.FormValidator

                If validator.ValidatePostback = True Then

                    ‘ DO SOMETHING WITH IT HERE


    If you have a redirect or thank you display message or processing to a next screen you’ll want to place that outside this code block.  For example on our contact form we do the following, on the first postback we send an email but on subsequent refresh of not validate postbacks we don’t send an email but still display the Thank you panel.

        Private Sub subForm_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles subForm.Click
            If Page.IsValid Then
                Dim validator As New TectonicConcepts.FormValidator.FormValidator
                If validator.ValidatePostback = True Then
                    Dim mail As New TectonicConcepts.TemplateMailer.SendTemplateEmail
                    mail.SendTemplateMail("Response from the Tectonic Concepts Website", "MailTemplates/ContactUsForm.txt", "", CMS.Settings.ContactFormSender, CMS.Settings.ContactFormRecipient, CMS.Settings.ContactFormBccRecipient, True, True, True, False, Me.Controls)
                End If
                ContactForm.Visible = False
                Contactus_Intro.Visible = False
                ContactUs_ThankYou.Visible = True
        End Sub

    The database setup script and FormValidator server control can be downloaded here.