Search code examples
c#asp.netajaxcontroltoolkit

JScript runtime error when using UpdatePanel


I am trying to create a dynamic UI using UpdatePanel of AJAX toolkit.

Let me explain the context of my application a bit. There are many profiles. Each profile has a number of product classes. Each product class has a number of products. I am implementing a comparison of products.

Profiles are represented by RadioButtonList (dynamically created). For each product class of selected profile a DropDownList need to be dynamically created that allows user to select a product of that class.

Everything is working fine on the first selection. However when I try to select another product and click submit the second time, the following error is thrown:

Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerServerErrorException: Invalid postback or callback argument. Event validation is enabled using in configuration or <%@ Page EnableEventValidation="true" %> in a page.

Any hints on why this error is thrown would be very helpful.

protected void Page_Load(object sender, EventArgs e)
{
    pnlDynamic.Visible = false;     
    if (!this.IsPostBack)
    {       
        LoadProfiles();  //Data binding is done for radio button list
    }
    else
    {
        btnSubmit.Enabled = true;
        GenerateProductUI(ProfileID); //DropDownLists are dynamically created and populated from database
        //ProfileID is the selected profile id
    }
}     


 <asp:UpdatePanel runat="server" id="UpdatePanel" updatemode="Conditional">
    <Triggers>
        <asp:AsyncPostBackTrigger controlid="rblProfiles" eventname="SelectedIndexChanged" />
    </Triggers>
     <ContentTemplate>      
        <asp:Panel ID="Panel1" runat="server">
            <asp:RadioButtonList ID="rblProfiles" runat="server" AutoPostBack="True"
                onselectedindexchanged="rblProfiles_SelectedIndexChanged">
            </asp:RadioButtonList>
        </asp:Panel>        
        <br />
        <asp:Panel ID="pnlDynamic" runat="server" Visible="false">                                  
            <asp:Panel ID="Panel2" runat="server">
                <asp:Table ID="table" runat="server"/>      <!-- Product dropdowns generated in table -->             
            </asp:Panel>                
        </asp:Panel>        
        <br />
    </ContentTemplate>
</asp:UpdatePanel>

<asp:Button ID="btnSubmit" runat="server" Text="Submit" onclick="btnSubmit_Click" CssClass="btnSubmit" AutoPostBack="True" /> 

<asp:UpdatePanel runat="server" id="UpdatePanel1" updatemode="Conditional">
    <Triggers>
        <asp:AsyncPostBackTrigger controlid="btnSubmit" eventname="Click" />
    </Triggers>
     <ContentTemplate> 

    <asp:Panel ID="pnlResult" runat="server" Visible="false">
     <!--Result displayed-->
    </asp:Panel>      
    <br />
    </ContentTemplate>
</asp:UpdatePanel>

Solution

  • IMPORTANT! EVERYONE WHO EVER DISABLES EVENT VALIDATION SHOULD UNDERSTAND WHAT HE IS DISABLING!

    Imagine that you have a blogging application (or a banking application) and there is a list of comments (or bank accounts) all users can see the comments (or the accounts) but only moderators (or managers) can delete them. So you write a check to switch the delete button visible property depending on the access of the user. Users who are not moderators (managers) cannot delete the comment (account). Problem solved.

    HOWEVER if you disable event validation a malicious user can send a post request claiming to have pressed the delete button despite the fact that it was never enabled for him. Normally the event validation would kick in and produce an exception but if it is disabled ASP.NET would not check if the button was visible and will just run the button click handler code and the comment (account) would be deleted. This can be prevented if you check if the user can delete in the button click event but you should also consider that another developer may come later and add another button (edit?) without noticing that event validation was disabled. Also now all other buttons on the page require the appropriate checks. Be very careful if you disable event validation!

    The error occurs because you are triggering a postback from a control which does not exist when the original page was rendered. One way to fix it would be to disable event validation for this page but you should make sure to check the credentials of the user requesting the change in the event itself otherwise it is a security issue because a user will be able to "press" a button that was not rendered at all (for example on products he does not have access to).

    You can disable event validation through the page directive:

    <%@ Page EnableEventValidation="false" ... %> 
    

    I believe it is also possible to set the update mode of the update panel to always instead of conditional which maybe will fix the issue (can you try it and tell us?) but this will increase the data sent over the network. If it is a good trade off depends on your use case, on the number and size of the update panels you have on the page (the more you have the worse). If it is an internal app or this UI is accessed relatively rarely I would go for this approach (assuming it works because I have not validated that).

    BTW this is not actually a script error. You are getting a client side script error simply because the error surfaces through an AJAX request. This is purely a server error that is raised because of a potential security issue with your code.