April
---
2007




Ajax UpdatePanel, UpdateProgress & MasterPages workaround.

There have been several technologies that have come and I have been a bit late in jumping on the bandwagon. Ajax is one of them.

"Ajax, shorthand for Asynchronous JavaScript and XML, is a web development technique for creating interactive web applications. The intent is to make web pages feel more responsive by exchanging small amounts of data with the server behind the scenes, so that the entire web page does not have to be reloaded each time the user requests a change. This is intended to increase the web page's interactivity, speed, and usability."[Wikipedia]

This is a very simple example where we query the the server for the server time. The time of the Page_Load event is also written, so we can compare it against the new value that is retrieved via Ajax, without refreshing the entire page. I have also added two updateProgress controls instead of one (you can have as many as you want), so we will have to call them both while we wait for a response.

I had been experimenting with Ajax a bit and came across this problem: While using an updatePanel together with an updateProgress control, and if, and only if, the control that start the postBack event (button1) is outside of the updatePanel control, you have to use additional Javascript to initiate a separate request. However, when you do that, and the postBack event (button1) is outside of the updatePanel control, then the updateProgress control is not called; even though the postback is made successfully, the animated gif (updateProgress) does not show. In order to fix that you have to add the Javascript shown below:



5/18/2012 3:32:29 PM: Time of Page_Load

5/18/2012 3:32:29 PM: Time of Ajax PostBack

javascript code

<script language="javascript" type="text/javascript">
  var prm = Sys.WebForms.PageRequestManager.getInstance();

  function CancelAsyncPostBack() {
    if (prm.get_isInAsyncPostBack()) {
      prm.abortPostBack();
    }
  }

  prm.add_initializeRequest(InitializeRequest);
  prm.add_endRequest(EndRequest);
  var postBackElement;

  function InitializeRequest(sender, args) {
    if (prm.get_isInAsyncPostBack()) {
      args.set_cancel(true);
    }
    
    postBackElement = args.get_postBackElement();

    if (postBackElement.id == 'Button1') {
$get('UpdateProgress1').style.display = 'block';
$get('UpdateProgress2').style.display = 'block';
    }
  }

  function EndRequest(sender, args) {
    if (postBackElement.id == 'Button1') {
      $get('UpdateProgress1').style.display = 'none';
      $get('UpdateProgress2').style.display = 'none';      
    }
  }
</script>

This will work perfectly fine if everything is on the same page. Notice how the Javascript references the control that will start the PostBack event by its name, as it should. However, when you are using MasterPages, you will realize that ASP.NET renames your controls with a different name and that is where the script will break...or simply put, the code never reaches the following code...

javascript code

if (postBackElement.id == 'Button1') {

...because Button1 simply does not exist. Your button control has been given another name, dynamically by the compiler. So, the easy fix to this is to use the names that the compiler will ultimately assign to your controls. Place a javascript alert in your code here:

javascript code

.....
    postBackElement = args.get_postBackElement();

    alert(postBackElement.id.toString());

    if (postBackElement.id == 'Button1') {
.....

javascript control name


The alert box will display the full control name. Copy everything before the Button1 and paste that in the javascript where the control names are used. Your code will look like this and it will work like a charm...

javascript code

<script language="javascript" type="text/javascript">
  var prm = Sys.WebForms.PageRequestManager.getInstance();

  function CancelAsyncPostBack() {
    if (prm.get_isInAsyncPostBack()) {
      prm.abortPostBack();
    }
  }

  prm.add_initializeRequest(InitializeRequest);
  prm.add_endRequest(EndRequest);
  var postBackElement;

  function InitializeRequest(sender, args) {
    if (prm.get_isInAsyncPostBack()) {
      args.set_cancel(true);
    }
    
    postBackElement = args.get_postBackElement();
    
    if (postBackElement.id == 'ctl00_cphBody_Button1'){
      $get('ctl00_cphBody_UpdateProgress1').style.display='block';
      $get('ctl00_cphBody_UpdateProgress2').style.display='block';
    }
  }
  
  function EndRequest(sender, args) {
    if (postBackElement.id == 'ctl00_cphBody_Button1') {
      $get('ctl00_cphBody_UpdateProgress1').style.display='none';
      $get('ctl00_cphBody_UpdateProgress2').style.display='none';
    }
  }
  </script>

Update: I was having some trouble with an error that came up every time I ran the experiment.

ajax error

After searching everywhere, I fixed this by simply adding EnableEventValidation="false" to my page declaration. I thought I'd post it here in case someone else is having the same problem...