Tuesday, August 14, 2012

Debugging EventValidation Error with Update Panel

if ur using UpdatePanel and never got this:
"Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerServerErrorException: 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."
then u should be a happy man.
but for those of u that has...
the classic scenario is u changing the control values with JS / JQ and on those cases the
ClientScriptManager.RegisterForEventValidation(Control.UniqueID, "new Value");
can help u, or even undoing the changes.

but here is how my code looks like this (no js / jq):

<asp:UpdatePanel ID="uppContact" runat="server" >

   <div class="divContactBoldText">Contact Name:</div>
   <asp:DropDownList ID="ddlContactsNames" runat="server" AutoPostBack="True"
   </asp:DropDownList><br />
   <div class="divContactBoldText">Title:</div>
   <asp:Label ID="lblTitle" runat="server" Text="No Title"></asp:Label><br />
   <div class="divContactBoldText">Status:</div>
   <asp:Label ID="lblStatus" runat="server" Text="??????????"></asp:Label><br />
   <div class="divContactBoldText">Function:</div>
   <asp:Label ID="lblFunction" runat="server" Text="No Function"></asp:Label><br />
   <div class="divContactBoldText">Email:</div>
   <asp:Label ID="lblEmail" runat="server" Text="No Email"></asp:Label><br />
   <div class="divContactBoldText">Phone:</div>
   <asp:Label ID="lblPhone" runat="server" Text="No Phone"></asp:Label><br />


and i got that error on my 2nd postback.
now how do u debug something like that? who started it?

well 1st we want to find out which control is making the problems so we can add a global.asax and put there this:

public class Global : System.Web.HttpApplication
   protected void Application_Error(object sender, EventArgs e)
       Exception ex = Server.GetLastError();

with nothing more than a breakpoint, then go to the InnerException and into its StackTrace there we get this:

   at System.Web.UI.ClientScriptManager.ValidateEvent(String uniqueId, String argument)
   at System.Web.UI.Control.ValidateEvent(String uniqueID, String eventArgument)
   at System.Web.UI.WebControls.DropDownList.LoadPostData(String postDataKey, NameValueCollection postCollection)
   at System.Web.UI.WebControls.DropDownList.System.Web.UI.IPostBackDataHandler.LoadPostData(String postDataKey, NameValueCollection postCollection)
   at System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

so we know know that a DropDownList control started it.

u all suspect "what did u JQueried the ddl", well i didnt touch it!
so how the hell do u debug that?!?
well some people suggested to to inherit the ddl with nothing to add and its simply not supports the EventValidation by default.
i cant do that cuz if i could i would just EnableEventValidation="false" to the entire page but this app is working with 2 DB's, 1 of them is managing money so we must be super careful.
and then some1 was smart enought to say to tell it to support the EventValidation but override this:

protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
return true;

cuz there is the problem and then it hit me! lets put a try catch there!
eventually i got to this (adding some tutorial for inexperienced like me) :
right click on the projecy => add => new item => ASP.NET Server Control
delete the rest cuz its just some tutorial and make it lool like this: (and drag it to the aspx designer)

using all kinda libraries...

namespace YOUR NAMESPACE (is there by default)
   [ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
   public class WebCustomControl1 : DropDownList
       protected override bool LoadPostData(string postDataKey,  System.Collections.Specialized.NameValueCollection postCollection)
           bool b = base.LoadPostData(postDataKey, postCollection);
           StringBuilder sb = new StringBuilder("no ex");
           foreach (string key in postCollection.Keys)
              var values = postCollection.GetValues(key);
             foreach (string value in values)
                sb.AppendLine(key + " - " + value);
File.WriteAllText("H:/" + postDataKey + "NoEx.txt", sb.ToString());
           return b;
       catch(Exception ex)
           StringBuilder sb = new StringBuilder(ex.Message);
           foreach (string key in postCollection.Keys)
              var values = postCollection.GetValues(key);
              foreach (string value in values)
                 sb.AppendLine(key + " - " + value);
File.WriteAllText("H:/" + postDataKey + "YesEx.txt", sb.ToString());
           return true;


*   [SupportsEventValidation()] - if u dont add this than u'll never get the exception cuz this control wont even support the EventValidation

and to my wonder - NO EXCEPTIONS!!!

but the secret is that i have another ddl in my page (some secret ha..) so i replaced it too with my shiny new WebCustomControl1 and there it was, my exception :D
but the txt files didnt show any difference :( , its still that secret hidden __EVENTVALIDATION.

now the thing is that i didnt yet use that ddl, and going throw my code it was mentioned once like this:

protected void Page_Load(object sender, EventArgs e)

    if (IsPostBack)
       "SELECT ID, FullName FROM _users",
       "ID", "FullName", "Choose User", mysql, out error);

ye of course it hit me - i tested it first but ye, it goes like this:
1. 1st page cycle, server writes ddl_users has X items
2. UPP posts with ddl_users having those X items, but nobody touches it
3. UPP, in case u didnt know does a full page cycle so server re-renders all his controls, this time writing that ddl_users has NO items
4. the UPP control cuts the rendered response according to himself and sends new data NOT oncluding the "new" emtpy ddl_users
5. UPP posts second time saying that ddl_users has the original X items but our serven says that he suppose to be empty HA HA - big bang!

solution: putting the if (IsPostBack) return; after re-creating the ddl solves it.
now that the point where u'll say "hey but its not my case", well ur right, just read the header - Debugging, i tought u some mechanics and how to debug (and overcome in some ways) this exception.

maybe some1 needs to send MS a request for .NET 5 - remember ur elders (values)

No comments:

Post a Comment