Thursday, January 10, 2008

Missing EventValidation because modal dialogue blocked rendering

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/missing_eventvalidation_because_modal_dialogue_blocked_rende.htm]



I saw an application giving this error:
System.ArgumentException: Invalid postback or callback argument. Event validation is enabled using in configuration or 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.
As is often the case, it "worked on my machine", but failed in production. It looked like one of those ghost bug things.
In this case, the problem was that the "EventValidation" field was missing entirely, so ASP.Net thought the page was corrupted:
  1. In production and QA, the page had a modal dialogue pop up. This was because both those environments ran in HTTPS, and that particular page had a JavaApplet on it, such that a modal dialogue popped up asking the user to confirm the security permissions.
  2. If the user clicked no, then that interfered with the final rendering at the bottom of  the page, which practically meant that just the "__EVENTVALIDATION" was never generated. The rest of the page looked the same.
  3. EventValidation was required to validate ViewState, so the server thought someone was hacking the page, and the Exception got thrown.
At first glance, a developer might just set Page EnableEventValidation="false", but that is a bad idea because it opens up a security hole (anyone could change your EventValidation value and exploit the app).
You can get an idea with this html code snippet, where I've substituted the JavaApplet call with an alert message (although the alert is truly modal, so you can't click a button until it's closed).
<body>
    <form id="form1" runat="server">
    <div>
   
  Text 1: this is the initial alert
   
  <script language="javascript" type="text/javascript">
    alert('yo!');
  </script>
 
  Text 2: this appears after the alert
 
    </div>
    </form>
</body
>
If you attach a debugger to the JS, you'll see that the second chunk of HTML text (Text 2) only gets rendered once the user closes the modal alert box. However, we can fix this by running the JavaScript code that called the applet in an asynch process via setTimeout, something like so:

<head runat="server">
    <title>Untitled Page</title>
    <script type="text/javascript" language="javascript">

    function DoStuff()
    {
      setTimeout("MyMethod()",500);
    }
    function MyMethod() {
       alert('yo!');
    }

    </script>   
</head>
<body>
    <form id="form1" runat="server" >
    <div>
    ASYNCH Hello world
   
    this is the initial code
   
  <script language="javascript" type="text/javascript">
    DoStuff()
  </script>
 
  this appears after the code
 
    </div>
    </form>
</body>
</html
>

No comments:

Post a Comment