Click here to Skip to main content
Click here to Skip to main content

ASP.NET Web Form Page Modified Prompt Using jQuery

, 4 Feb 2011
Rate this:
Please Sign up or sign in to vote.
When the user modifies ASP.NET web form fields and leaves the web form without saving it, we should notify the user about the modified data.

Introduction

In the web app world, it is quite important for an application to be sure about the integrity of the data. In the article's context, what this means is when the user modifies form data and leaves the form without saving it, the application prompts the user: 'Form is modified, do you want to save?' This is a quite common requirement for web developers. But the form might have different controls on it, and handling each control for each type of control will result in a code that is tightly coupled to the application. What if the form changes tomorrow, adding some fields or removing existing fields? It will result in additional maintenance work every time.

Background

In one of our projects, I was asked to create a user prompt when the user modifies the web form and leaves the web form without saving it, in order to save the integrity of the form data. Now, the question is, do we write code on the server side? Or on the client side? If we write code on the server side, every time the user leaves the web form, it should post back data to the server and verify whether the form data was modified or not, and based on that, it will have to create the user prompt.

The idea here is, we need to first capture the initial values when the form is loaded, also capture the final values' snapshot before the user leaves the form, and compare both the initial and final values; if there is any difference, prompt the user saying, "The form was modified, do you want to save?', else let the user go to the next page.

If we carefully observe the ASP.NET page life cycle, ViewState can do this for us. We can compare postback data with ViewState values. If there is any difference between the two, we can prompt the user on the client side saying, 'Form modified. Do you want to Save?' But this approach will have its side affects. If the web form contains AJAX UpdatePanels, they do partial postbacks for the actions they are responsible for. In this case, the ViewState will not be the same as the ViewState that is loaded the first time. The ViewState will get updated incrementally every time, and we will not have the option to compare the initial and final values. Because the ViewState is always updated with the current values on the form.

Now the other option would be client side scripting, using JavaScript. If we write code using JavaScript for each control on the form to compare the initial and final values, eventually it will become too much code, which will result in maintenance headaches in cases where the form fields are dynamic.

We can always browse through each form control using DOM traversing, and load them up into an initial and final dictionary, and compare the differences, which would always be a working option irrespective of whether the form has UpdatePanels or has partial post backs etc. But here, we need to verify, for each control, the type of the control in order to get the value of the control. So a better approach for the above is to use jQuery. jQuery selectors are good at selecting controls based on the type of controls given.

Using the Code

This sample uses Visual Studio 2008 SP1. Using the same version of Visual Studio is recommended; if you don't have the same version, download the source code and create a web application using the version you have and add the files to the project manually. The expected minimum version is Visual Studio 2005.

To explain it very simply, I took a simple employee site which contains two pages, default.aspx and Roles.aspx, and a site1.master page which holds the navigation for these two pages.

The picture below shows the code structure:

FormCheckModified.JPG

Below is the code in ItemValueDictionary.js:

//Load Current values for all
//the text boxes, radio buttons, checkboxes, select buttons,
//adding another text box will be automatically
//picked up by the code as the Jquery selectors are 
//used for each control type. 


function LoadCurrentValues(dictionary) {
    $("input:text").each(function() {
    AddElementToDictionary(dictionary,this.id, this.value);
    });
    //alert(this.value )});
    $("input:radio").each(function() {
    AddElementToDictionary(dictionary,this.id, this.checked);
    });
    $("input:checkbox").each(function() {
    AddElementToDictionary(dictionary,this.id, this.checked);

    });
    $("select").each(function() {
    AddElementToDictionary(dictionary,this.id, $("#" + this.id).val());
    }
    )
}


// to compare the initial form values and current form
//values and returns true if they are same or false if they are different.

function CompareDictionaries(InitialDictionary) {
    CurrentDictionary = new Array();
   
    //At any point while the application is runing
    //it will load the current values, for each control in the form. 
    LoadCurrentValues();
    // Initially check for the number of controls in the
    // Initial Dictionary and in the final dictionary.
    // If the number of controls don't match then
    // form is changed in such a way that some of the controls
    // are hidden or some of the controls loaded as part of the page actions.
    // In these cases, Form save dailogue should trigger
    
    if (InitialDictionary.length != CurrentDictionary.length) {
        return false;
    }
    //number of controls are same, next check if there
    //is any change in the values of each controls
    else {
    
     for(i=0;i<InitialDictionary.length;i++)
     {
       if((InitialDictionary[i].name==CurrentDictionary[i].name) && 
          (InitialDictionary[i].value != CurrentDictionary[i].value))
       {
           return false;
       }
     }
     return true;
    }
}

In the above code, LoadCurrentValues(dictionary) loads the snapshot of each control when the method is called, and the dictionary will have the loaded values. After the page DOM is rendered, the LoadCurrentValues(dictionary) method will be called to load the initial values of the controls. It will prepare a dictionary of IDs and values, with the initial values.

Similarly, LoadCurrentValues(InitialDictionary) will load the current values when the user leaves the form page, and prepares a dictionary of IDs and values, with the current values. The CompareDictionaries() method compares the initial dictionary and the current dictionary. If they are different, then it will return false, else it returns true.

The code below is the place where the LoadInitialValues() method will be called. This is the master page for both of the pages.

$().ready(function() {
           //To capture form initial values
           InitialDictionary = new Array();
            LoadCurrentValues(InitialDictionary);
            $("a[id*=hl]").click(function() {
                if (!CompareDictionaries(InitialDictionary)) {
                     return confirm('Form is modified, Do you want to continue');
                }
            }
        )
     }
)

Points of Interest

Using jQuery to solve the above problem is good in terms of the amount of code that we have written. Also, if we change the form in future, like add a few textboxes or checkboxes, the preset code should automatically pick up those controls with no code changes required.

Disclaimer

The sample provided in this article is just to give the reader an idea of how to approach the above said problem. It might be necessary to tweak the solution to your needs. This sample can not be used for direct production deployment.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

RamuSangabathula
Architect
India India
I have around 9 years of experience in Microsoft technologies, .Net 2.0,3.5, Asp.net MVC developed small to medium scale products using Silverlight 2.0, Asp.net Ajax technologie and Javascript frameworks.

Comments and Discussions

 
GeneralCould not download the code PinmemberMember 45650632-Aug-12 1:40 
GeneralRe: Could not download the code PinmemberMember 45650632-Aug-12 1:45 
QuestionHow to use this code on page Pinmemberaditya.u.rane2-May-11 21:08 
GeneralUpdate panels Pinmembergfrenkel19-Apr-11 20:01 
AnswerRe: Update panels Pinmembercorol123410-Apr-11 8:22 
GeneralNice post PinmemberShahriar Iqbal Chowdhury4-Feb-11 8:31 
Generalnice article PinmemberTanu Reddy25-Jan-11 18:56 
GeneralMy vote of 2 Pinmemberaprishchepov24-Jan-11 18:01 
AnswerRe: My vote of 2 PinmemberRamuSangabathula25-Jan-11 15:55 
GeneralImprovement PinmemberSteve Wellens24-Jan-11 5:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 4 Feb 2011
Article Copyright 2011 by RamuSangabathula
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid