Friday, 28 March 2008

Dirty Checking in ASP.NET (revisited)

An regular request from my clients is to have a warning when a user navigates away from a web page. This is something taken for granted in the Windows Forms world - but there is no native support for this functionality in the ASP.NET framework. In the past I have done some more manual workarounds with javascript for critical pages but there are some better options out there.

There are a few different sample implementations on the web for checking that you have made changes to your ASP.NET page (aka dirty checking):

http://www.codeproject.com/KB/aspnet/EWSWebPt2.aspx
http://www.codeproject.com/KB/ajax/ajaxdirtypanelextender.aspx

One of the issues with checking for changes in controls is that there is limited support out of the box for whether HTML controls have changed on the client side. Also dirty checking is server side is unneccessary overkill and involves unneccessary postbacks (partial or otherwise).

The common theme amongst the approaches to this problem is to :


  1. In Page PreRender, save all original values of editable controls into hidden fields

  2. When checking for dirty (e.g. navigating away from the page) – get all current values from editable controls and compare with the values in the hidden control – and warn if dirty

  3. On Save, mark all controls as not dirty (by updating the value in the hidden control).

Another possible approach is to hook into the onchange event - http://www.w3schools.com/jsref/jsref_onchange.asp - I originally thought this approach would be more complicated to implement as it has to handle the change activity of different controls specifically rather than just checking the value.

However, there is a VERY simple way to do this check with a few lines of javascript - see the code below (thanks to Steve Krizanovic for pointing out this neat trick):






<html>
<head>
<style type="text/css">
.hide
{
display: none;
}
.show
{
display: inherit;
}
</style>
</head>
<body>

<script>
//Demo of completely client side dirty flag.

function setDirty()
{
document.body.onbeforeunload=showMessage;
//debugger;
document.getElementById("DirtyLabel").className = "show";
}

function clearDirty()
{
document.body.onbeforeunload = "";
document.getElementById("DirtyLabel").className = "hide";
}


function showMessage()
{
return "page is dirty"
}

function setControlChange()
{
if(typeof(event.srcElement)!='undefined')
{
event.srcElement.onchange=setDirty;
}
}

document.body.onclick=setControlChange;
document.body.onkeyup=setControlChange;

</script>
<h1>Demo: Dirty Page Client Side Warnings</h1>
<div id="DirtyLabel" style="color: Red;" class="hide">
Page is Dirty</div>
<input id="Text1" type="text" />
<input id="Text2" type="text" />
<input id="Radio1" name="testRadio" type="radio" checked="checked" title="Option 1"
value="1" />
<input id="Radio3" name="testRadio" type="radio" title="Option 2" value="2" />
<input id="Radio2" name="testRadio" type="radio" title="Option 3" value="3" />
<select name="DropDown">
<option value="" selected="selected">Select Country</option>
<option value="United States">United States</option>
<option value="United Kingdom">United Kingdom</option>
<option value="Afghanistan">Afghanistan</option>
</select>
</input>
<input id="Button1" type="button" value="Save" onclick="clearDirty();" />
</body>
</html>

4 comments:

Transplante de Cabelo said...

Hello. This post is likeable, and your blog is very interesting, congratulations :-). I will add in my blogroll =). If possible gives a last there on my blog, it is about the Transplante de Cabelo, I hope you enjoy. The address is http://transplante-de-cabelo.blogspot.com. A hug.

Chris in Wilmington, NC said...

Thank you, David.

It works great! I do have one question. Where is the confirm box coming from in your showMessage function?

neil said...

Very elevant solution David. Thankyou for posting it.

Omkar said...

Thank u It works great! I do have one question. Where is the confirm box coming from in your showMessage function?