Search code examples
c#asp.net.nethtml-selecteventvalidation

How to pass Event Validation when editing a select list from JavaScript


I have two select lists in my ASP.NET site that are filled by the server with some elements.

// .aspx
<asp:dropdownlist id="abc" runat="server"></asp:dropdownlist>
<asp:dropdownlist id="def" runat="server"></asp:dropdownlist>

// .aspx.cs
abc.Items.Add(new ListItem("element1", "value1"));
def.Items.Add(new ListItem("element1", "value1"));

Due to too complicated reasons to explain right now, I also need to modify the options of the select lists with JavaScript, adding some values.

// In the <head> of the .aspx page
var abcList = document.getElementById("abc");
var defList = document.getElementById("def");
var newAbcElement = new Option("element2", "value2", false, false);
var newDefElement = new Option("element2", "value2", false, false);
abcList.options[abcList.length] = newAbcElement;
defList.options[defList.length] = newDefElement;

Of course, this will mess up Even Validation as soon as I send the form back to the server (be it by submitting or as a PostBack from some other form elements with AutoPostBack="true").

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.

Now, I don't have the resources and budget to completely overhaul the whole page design, so: What is the fastest and easiest way to change the dropdownlist that does not mean I have to rewrite the whole thing?

So that the values added via JavaScript are recognized by my CodeBehind file when submitting the form?


Solution

  • Ok, here is one more option for you. You can add those items to your lists using AsyncPostBackTrigger.

    Some hidden fields:

    <asp:TextBox ID="newItemsForAbc" runat="server" style="display:none;"></asp:TextBox>
    <asp:TextBox ID="newItemsForDef" runat="server" style="display:none;"></asp:TextBox>
    <asp:Button ID="addNewItems" runat="server" OnClick="addNewItems_Click"
      style="display:none;" />
    

    The Update Panel:

    <asp:UpdatePanel runat="server" ID="UpdatePanel" UpdateMode="Conditional">
       <ContentTemplate>
         <asp:dropdownlist id="abc" runat="server"></asp:dropdownlist>
         <asp:dropdownlist id="def" runat="server"></asp:dropdownlist>
       </ContentTemplate>
       <Triggers>
         <asp:AsyncPostBackTrigger ControlID="addNewItems" EventName="Click" />
       </Triggers>
     </asp:UpdatePanel>
    

    JS Function for doing an async post back:

    <script type="text/javascript"> function UpdateStuff(value1, value2)
    {
       var abcItems = document.getElementById("<%= newItemsForAbc.ClientID %>");
       var defItems = document.getElementById("<%= newItemsForDef.ClientID %>");
       abcItems.value=value1;
       defItems.value=value2;
       __doPostBack("<%= addNewItems.ClientID %>","");
    }
    </script>
    

    Server-side function that handles button click:

    protected void addNewItems_Click(object sender, EventArgs e)
    {
        string[] n1 = newItemsForAbc.Text.Split(';');
        string[] n2 = newItemsForDef.Text.Split(';');
    
        foreach(string i in n1)
        {
             abc.Items.Add(new ListItem(i, i));
        }
    
        foreach(string i in n2)
        {
             def.Items.Add(new ListItem(i,i));
        } 
    }
    

    To Update Your Lists:

    var newAbcElements = "Element1;Element2;Element3";
    var newDefElements = "Element4;Element5";
    UpdateStuff(newAbcElements, newDefElements);
    

    Final note: This piece of code probably will not do the job for you as it is. You may need to change the way you store new items in a string, thus splitting/parsing would change too. You may even need different strings for displaying a list item and its actual value. But I believe you get the basic idea.