This is one the common issues that a lot of ASP.NET
beginners face, post and ask about.
Problem description
Typically, they post the error message as below and seek for resolution without sharing much about what they were trying to do.
[ArgumentException: Invalid postback or callback argument. Event validation is enabled using 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.]
Though, error stack trace itself suggests a quick resolution by setting eventvalidation
off, it is not a recommended solution as it opens up a security hole. It is always good to know why it happened and how to solve/handle that root problem.
Assessment
Event validation is done to validate if the origin of the event is the related rendered control (and not some cross site script or so). Since control registers its events during rendering, events can be validated during postback or callback (via arguments of __doPostBack
). This reduces the risk of unauthorized or malicious postback requests and callbacks.
Refer: MSDN: Page.EnableEventValidation Property
Based on above, possible scenarios that I have faced or heard that raises the issue in discussion are:
Case #1:
If we have angular brackets in the request data, it looks like some script tag is being passed to server
Possible Solution:
HTML encode the angular brackets with help of JavaScript before submitting the form, i.e. replace “<” with “<” and “>” with “>”
function HTMLEncodeAngularBrackets(someString)
{
var modifiedString = someString.replace("<","<");
modifiedString = modifiedString.replace(">",">");
return modifiedString;
}
Case #2:
If we write client script that changes a control in the client at run time, we might have a dangling event. An example could be having embedded controls where an inner control registers for postback but is hidden at runtime because of an operation done on outer control. This I read about on MSDN blog written by Carlo, when looking for same issue because of multiple form tags.
Possible Solution:
Manually register control for event validation within Render method of the page.
protected override void Render(HtmlTextWriter writer)
{ ClientScript.RegisterForEventValidation(myButton.UniqueID.ToString());
base.Render(writer);
}
As said, one of the other common scenario reported (which looks like falls in the this same category) is building a page where one form tag is embedded in another form tag that runs on server. Removing one of them corrects the flow and resolves the issue.
Case #3:
If we re-define/instantiate controls or commands at runtime on every postback, respective/related events might go for a toss. A simple example could be of re-binding a datagrid on every pageload (including postbacks). Since, on rebind all the controls in grid will have a new ID, during an event triggered by datagrid control, on postback the control ID’s are changed and thus the event might not connect to correct control raising the issue.
Possible Solution:
This can be simply resolved by making sure that controls are not re-created on every postback (rebind here). Using Page
property IsPostback
can easily handle it. If one want to create control on every postback, then it is necessary to make sure that the ID’s are not changed.
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostback)
{
// Create controls
// Bind Grid
}
}
Conclusion
As said, easy/direct solution can be adding enableEventValidation="false"
in the Page
directive or Web.config
file but is not recommended. Based on the implementation and cause, find the root cause and apply the resolution accordingly.
Keep learning!