Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__doPostBack only works if there is a LinkButton, Calendar or WizardStep control on the page

I have identified a problem with __doPostBack and found a work around. I am seeking an explanation for the cause and/or a better solution than my work around.

Scenario: I have a dropdown populated with the values; "-Select-", "One" & "Two". If the user selects "One" than client side script is executed. If the user selects "Two" than server side script is executed.

Problem: The client script initiates the postback by calling __doPostBack. However, no post back actually occurs unless there is also a LinkButton, Calendar or WizardStep control on the page. I actually went through all of the standard tools in the Visual Studio Toolbox and tested them all. It has to be one of those three.

Work Around: Add a link button surrounded by a span with display set to none.

<span style="display:none;">
    <asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
</span>

Question: Can somebody provide an explanation for this behavior or provide a better fix than my "Work Around"?

Source - Javascript (I placed it between the head tags)

<script language="javascript" type="text/javascript">
    function DropDownList1_change(elementRef) {
        var selectedIndex = elementRef.selectedIndex;
        if (selectedIndex > 0) {
            var selectedValue = elementRef.options[selectedIndex].value;
            if (selectedValue == "One") {
                alert("Because you selected 'One', special javascript code will be executed");
                // Special javascript code goes here
                return;
            }
            else if (selectedValue == "Two") {
                // Special server code gets executed on server DropDownList1_SelectedIndexChanged
                __doPostBack('DropDownList1', '');
            }
        }
    }
</script>

Source - ASPX Controls

    <asp:DropDownList ID="DropDownList1" runat="server"  onchange="DropDownList1_change(this)" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
        <asp:ListItem>-Select-</asp:ListItem>
        <asp:ListItem>One</asp:ListItem>
        <asp:ListItem>Two</asp:ListItem>
    </asp:DropDownList>
    <br />

    <!-- For some unknown reason __doPostBack only works if there is a LinkButton, Calendar or WizardStep control on the page -->      
    <span style="display:none;">
        <asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
    </span>

    Time of last Post Back: <asp:Label ID="Label1" runat="server"></asp:Label><br />
    Time of OnSelectedIndexChanged: <asp:Label ID="Label2" runat="server"></asp:Label>

Source - Code Behind

    protected void Page_Load(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToLongTimeString();
    }

    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        Label2.Text = DateTime.Now.ToLongTimeString();
    }

Additional Resource - I found the following article after posting this question. Its a very old Microsoft article and the only Microsoft article I found that mentions the specific limitation of DropDowns, return values & postbacks. I haven't digged deep into their solution and not sure time will allow me to. Mainly posting it in case my solution fails down the road or doesn't work for someone else.

Intuitively you might think adding a confirm dialog box for a DropDownList is identical to adding such a dialog box for a Button Web control. That is, simply set the DropDownList's client-side onchange attribute to something like: return confirm(...);. using: DropDownListID.Attributes("onchange") = "return confirm(...);" Unfortunately, this won't work as desired because an AutoPostBack DropDownList's onchange attribute will be set to a bit of JavaScript that causes a postback, namely a call to the client-side __doPostBack function. When setting the onchange attribute programmatically yourself, the end result is that the rendered client-side onchange event handler has both your code and the call to __doPostBack:

The article is long so search for "Confirmation with AutoPostBack DropDownLists"

https://msdn.microsoft.com/en-us/library/aa479302.aspx

like image 949
Dave Avatar asked Aug 03 '16 17:08

Dave


People also ask

What is the use of __doPostBack in a form?

The function __doPostBack is generated only if a control in the form needs it to perform postbacks. This includes controls like the LinkButton and other controls for which AutoPostBack is set to true. In fact, only the Button and ImageButton controls can perform postbacks without __doPostBack (see this article ).

How to add__doPostBack () function to the page output?

To know this, drag a LinkButton control into the page and execute the page. You can see the __doPostBack () function will get automatically added to the page output. Refer below,

How to pass the UniqueID of the control in the postback?

You should pass the UniqueID of the control when you have associated master page in the __doPostBack () method above. When you call __doPostBack () method without any argument (as in section Raising Postback from Javascript) then it will call only the Page_Load event.

When to use__doPostBack () in ASP NET?

As i said earlier, ASP. Net runtime will insert the definition of __doPostBack () automatically only when there is a control that can initiate a postback in the page. In this case, your page might not have a control that can raise the postback. ASP.


1 Answers

There are 2 solutions.

Solution 1: A better work around than adding a link button surrounded by hidden span tags is to add the following to the page load event. This ensures that the function __doPostBack is available.

protected void Page_Load(object sender, EventArgs e)
{
    Page.ClientScript.GetPostBackEventReference(this, string.Empty);
}

The function __doPostBack is generated only if a control in the form needs it to perform postbacks. This includes controls like the LinkButton and other controls for which AutoPostBack is set to true. In fact, only the Button and ImageButton controls can perform postbacks without __doPostBack (see this article). For example, we can see in the HTML output that a LinkButton is rendered this way:

<a id="lnk" href="javascript:__doPostBack(&#39;lnk&#39;,&#39;&#39;)">My link</a>


Solution 2: The following approach achieves the same thing without using __doPostBack.

In the present case, you could set AutoPostBack="true" for the DropDownList:

<asp:DropDownList AutoPostBack="true" onchange="if (!confirmPostBack(this)) return false;" ... >

The onchange event handler would return false when you want to prevent the postback. The Javascript function could be something like this:

function confirmPostBack(ddl)
{
    if (condition) {
        ...
        return true;
    } 
    else {
        ...
        return false;
    }
}

Important: The onchange event handler should not return anything to allow the postback to occur. You can use this syntax:

onchange="if (!confirmPostBack(this)) return false;"

For reasons probably explained in the article mentioned in the question, the following syntax does not work. Returning true still prevents the postback.

onchange="return confirmPostBack(this);" // Does not work!
like image 183
ConnorsFan Avatar answered Oct 23 '22 15:10

ConnorsFan