Invalid postback or callback argument - AJAX Control Toolkit

I was working to add some Ajax interactivity to a page that needed some asynchronous workings. Unfortunately, after displaying a ModalPopupExtender and the user clicking the Close button on the “popup”, the page would throw the following exception:

System.ArgumentException occurred
  Message="Invalid postback or callback argument.  Event validation is enabled using <pages enableEventValidation=\"true\"/> in configuration or <%@ Page EnableEventValidation=\"true\" %> in a page.  For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them.  If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation."
  Source="System.Web"
  StackTrace:
       at System.Web.UI.ClientScriptManager.ValidateEvent(String uniqueId, String argument)
  InnerException:

There are lots of explanations out there for this kind of problem, but none of the common answers really fit. The most common answer was to disable event validation. That wasn’t a good answer for me, I don’t think disabling an important security feature because you have complex code is a good solution. The other common answer was to override the render event to register the control posting back with the ScriptManager. This did not work at all for me.

After finding an reading through this post and the comments, I realized the problem was indeed in the code. After the call to ModalPopupExtender.Show(), the original code was re-binding a grid on the page. This order of events was causing the problem. I changed the binding to occur before the call to the ModalPopupExtender by changing which event containing the rebinding call, and the error went away.

Posted: Monday, March 23, 2009 8:46:00 PM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
.Net 3.0 | .Net 3.5 | ASP.NET | JavaScript/AJAX

Linq Foray

I’m working on a website with lots of user controls interacting with one another using ASP.NET Ajax using events. So I end up needing to find other controls often, especially within repeaters. Nested controls all over the place. I found this wonderful post about using an extension method to the Controls Collection that flattens the tree and allows for much simpler Linq queries. The extension method adds and All() function which is seriously useful.

Posted: Sunday, March 22, 2009 9:27:00 PM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
.Net 3.5 | ASP.NET | JavaScript/AJAX | Linq

Using XMLHTTP in Javascript

I attended a terrific meeting tonight of GANG, the Great Lakes Area .Net user Group, based in the Detroit-area. The main presenter was Jason Beres who gave an excellent presentation on ASP.Net tricks, many of them utilizing Javascript. One of my favorites came up in discussion and I agreed to post the code snippet here.

I have used this techniqe mainly on classic ASP pages as a way to populate secondary dropdown lists before ASP.Net and control-based postbacks came along. It still works with ASP.Net... BUT...the secondary listbox is not in the Viewstate so it's value isn't set properly when accessing the control in server code on the postback where you handle the data. The secondary list's selected value is still in the Request.Form collection though. It is still a great technique to use to fetch data from the server without reloading the page.

The technique is IE-only as it uses an ActiveX object (XMLHTTP) in the Javascript. It also uses the XML DOM to parse the response from the server. In this example the server is an ASP page, but it could easily be a web service as well with the addition of one a little more code. This code is related to a previous post where I used VBA to enable Excel to be a web service client.

Here is the Javascript function:

/*  Purpose: Fill secondary list boxes with content
    Arguments:  oItem - the primary dropdownlist object
                sFieldName - The name of the field filling the secondary list
                oDestination - the secondary list object
    Returns: None, fills list box using MSXML*/
 
function fillSecondary(oItem, sFieldName, oDestination)
{
  var nValue = oItem[oItem.selectedIndex].value;
 
  var xmlHTTP = new ActiveXObject("Microsoft.XMLHTTP");
  xmlHTTP.open("POST", "./listboxesXML.asp", false);
  xmlHTTP.send('<' + sFieldName + '>' + nValue + '    
  var xmlDOM = new ActiveXObject("Microsoft.XMLDOM");

  xmlDOM.loadXML(xmlHTTP.ResponseText);

  if (xmlDOM.parseError != 0)
  {
   alert("Error occurred: " + xmlDOM.parseError.reason);
   return false;
  }

  var oNode = xmlDOM.documentElement.firstChild;
  var n=0;
  if(oNode != null)
  {
   //Clear out the secondary list box, it might already have items
   oDestination.length = 0;
   while (oNode != null)
   {
    oDestination[n] = new Option(oNode.text, oNode.attributes(0).text);
    n++;
    oNode = oNode.nextSibling;
   }
   if(n==1)
    oDestination.selectedIndex = 0;
  }
}

In the HTML on the page, add an OnChange handler to the primary dropdown list to call the Javascript when the user changes the value:

<FORM id=“Form1“>
<SELECT id=“Primary“ onchange=“fillSecondary(this, “Primary“, document.form1.secondary)“><OPTION value=“1“ selected>A list Item</OPTION></SELECT>
<SELECT id=“Secondary“ name=“Secondary“></SELECT>
</FORM>

The classic ASP page (listboxesXML.asp) called by the Javascript looks like this:

Dim xmlDOM   'XML DOM object
Dim oRS    'Recordset for child records
Dim sXML   'XML String returned to browser
Dim oNode   'DOM node containing data for searching
Dim sType   'The type/name of the unknown child node

set xmlDOM = Server.CreateObject("MSXML2.DOMDocument")
xmlDOM.async = false
xmlDOM.Load Request
xmlDOM.setProperty "SelectionLanguage", "XPath"
if xmlDOM.parseError = 0 then
 'Select the request node
    set oParent = xmlDOM.selectSingleNode("request")
    'Get the child of the request node
    set oNode = oParent.firstChild
    'Store the child's value
    sSearchValue = oNode.Text
    'Store the child's name
    sType = oNode.nodeName

    set oRS = Server.CreateObject("ADODB.recordset")

    'Fetch the appropriate data into the recordset using sType to tell which
    '  secondary list we should be fetching, in this case it is called “secondarytype“

    'ADO Code should be here, removed for brevity

 if not oRS.EOF then
  'Build a response XML string
  sXML = ""
  while not oRS.EOF
   sXML = sXML & "<" & sType & " id=""" & oRS.Fields(0).Value & """>"
   sXML = sXML & Server.HTMLEncode(ors.Fields(1).Value) & "   oRS.MoveNext
  wend
  sXML = sXML & "
"
  oRS.Close
 else
  sXML = ""
  sXML = sXML & "<" & sType & " id=""0"">"
  sXML = sXML & "None listed  sXML = sXML & "
"
  oRS.Close
 end if
 set oRS = nothing
Response.Write sXML
else
Err.Raise 1, "ParseError", "There was a parse error in the request."
end if

This can be very tricky to debug if you have any problems. Try looking at the xmlHTTP.ResponseText in an alert in the Javascript function to see any 500 errors generated by the server.

Posted: Thursday, June 17, 2004 2:43:28 AM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
ASP.NET | JavaScript/AJAX