In the last post we looked at the job event validation performs, and how we can trigger a validation error with some innocent JavaScript. If we receive exceptions because of event validation, we have to disable the feature, or learn how to work with the event validation.
Pros: Easy to do
Cons: Less secure
Bertrand Le Roy wrote a post back in 2004: “Please, please, please, learn about injection attacks!”. Event validation is a feature designed to help prevent injection attacks (of course it can't prevent attacks all by itself).
We can disable event validation for an entire site in the web.config file.
Alternatively, we can disable validation for a single page.
Pros: Feel validated
Cons: We need to register all the legal post values before the page is sent to the client - this isn't always possible or practical
When we last left our application, we had a DropDownList with three legal values: “1”, “2”, or “3”. The problem was that client side script was adding a 4th option: “4”. If the user selected the 4th option and posted the form to the server, the server would throw an exception because it didn’t know “4” was a legal value.
The key to passing validation is to let ASP.NET know the value “4” is legal with the RegisterForEventValidation method of the ClientScriptManager class.
RegisterForEventValidation must be called during the rendering phase, so we need to override a Render method. We could start by overriding the Render method of our web form. Plug the following code right below the Page_Load method from the previous post.
Remember event validation works by combining the hash of a control’s UniqueID property and a hash of each legal value for that control. The RegisterForEventValidation method accepts both of the calculation inputs as parameters. The method stores the result in a dictionary, and the page adds saves the dictionary as a hidden field on the client.
Adding the RegisterForEventValidation responsibility to the Page class is less than ideal, as the web form suddenly has to know about the DropDownList and its event validation problems. An alternate solution would be to build our own control.
A crucial step in the code is to add the SupportsEventValidation attribute to the class. If this attribute is not present, all the RegisterForEventValidation work is in vain. The runtime does not validate events for controls that do not have the SupportsEventValidation attribute present, nor does the runtime does look at the custom attributes of the control’s base class. The table of controls supporting event validation that appeared in the last post was output by a simple program that looped through all the Types in the System.Web assembly looking for the SupportsEventValidationAttribute.
In our example, we knew we only had one additional legal value – the value “4”. We need to call RegisterForEventValidation for every legal value the control might postback. This raises a couple issues because we may not know all of the legal values the control can take. AJAX might populate the control with values from a web service call that is bridged to a third party. Another issue is that the number of legal values might be extremely large.
Unfortunately, ASP.NET doesn’t expose a property to disable event validation for a single control – this would be a nice feature to have. However, if we create a custom control and leave off the SupportsEventValidation attribute, we’ll effectively disable event validation for instances of that class.
Comments
thanks.
I was having this problem with some AJAX stuff that places two input texts and submit button in a div container.
My first thought was: OK, when the page tries to process the POST data it can't find the new controls I added, so as a clever man I am :) I'm going to add the controls in the Page_Init event when proceeds.
It crashed again, and now I know what, the event validation engine doesn't wait those post values at all!!!
My postback validation pass but event validation fails miserably.
I have disabled the event validation in the <pages /> section. But I agree the ideal solution would be to enable it in a control-basis. Thanks !!!
how should I do that?
Thanks
As long as the control building takes place on the server you should be ok. It's only when a value appears that wasn't in the control on the server side that there is a problem, I believe.
So lets say I have an ImageButton building on at runtime on Page_Load adding attributes such as CallbackReference. When selecting one of these ImageButton a (or more) DropDownList are filled in with the Callback process using Javascript!
Shouldn't I have any problems? So EventValidation is not needed here or what?
so for each value that can be populated I have to register it with RegisterForEventValidation ?
I'm still getting the idea of how to use this RegisterForEventValidation when you have controls that are built on runtime and are populated dynamically!
the above example is when you know the items of the dropdownlist .. but when you don't?
You are populating the list with values using javascript, but you don't know what the possible values will be? Are the values coming from stuff the user types into the web page?
If that is the case you'll have to disable event validation for the page, or derive a new control from DropDownList like in the example above, but leave off the SupportsEventValidation argument.
the values are coming from a database according to the number of ImageButton clicked. Each ImageButton has an CallbackReference and when click a dropdownlist is filled with data from the database...
I think you'll have to disable event validation.
Your english is fine, I was just slow to understand the problem.
but I would have a security breach in my web page or not? I could easily make it false EventValidation on Page start but what about security?
For the DropDownList you can always compare the incoming value against the legal values in your database.
the Textbox entry is not always required by the user.
to the Dropdownlist it is a solution (compare with db) although I thought I can make use of the RegisterForEventValidation
I made a page where I created a control that overrides dropdownlist. I place it on the page using the placeholder control. Now, I do this because I'm dynamically adding options to the dropdown using javascript as described here in this article. The thing is:
When I postback (hitting a button), I am unable to see the currently selected value in the dropdown. Is there a way to communicate the selectedValue during the postback?
protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
{
string strArgs = eventArgument;
base.RaisePostBackEvent(sourceControl, eventArgument);
}
It occurs simply because, with a slow connection, I can raise a postback before the page has fully loaded - e.g.
- User links to the ASP.NET page, page loads fully.
- User clicks a button, and the page transfers.
- User realises they've made a mistake, and quickly clicks another button, just as the page is half-loaded in the browser.
- Error page appears.
I guess there's not really a decent way to get round this, it's fairly obvious that only sending back half the page will generate a validation error.
Any suggestions?
can anyone help me ?
Thanks
I designed a custom GridView by template field
and add an ImageButton to it,at run time when i press button "invalid postba..." exception was triggered,but girdview just show data and no modified data ,no new data ,no script,...
just when button clicked the page redirected to oder page with a query string.
but i still have problem!
<asp:ImageButton runat="Server" ID="btnBuy"
CommandName="Buy" CommandArgument='<%#EVAL("ID")%>'/>
can anyone help me?
Page.ClientScript.GetPostBackEventReference(textbox1, "", true);
Hope this helps some one in need
You wrote:
A crucial step in the code is to add the SupportsEventValidation attribute to the class. If this attribute is not present, all the RegisterForEventValidation work is in vain. The runtime does not validate events for controls that do not have the SupportsEventValidation attribute present, nor does the runtime does look at the custom attributes of the control’s base class.
I tried to prevent the Event Validation error by extending DropDownList and leaving off the SupportsEventValidation attribute. It did not prevent the error.
Did I miss something?
Thank you very much for an excellent post.