ASP.Net Web Forms: Error when javascript function executed, Bootstrap integrated.

Srinivas Chintamaneni 0 Reputation points
2024-11-13T04:43:25.4266667+00:00

Hello All,

I have an issue with the ASP.Net Web Forms application that is returning an AJAX error when the javascript function is executed. Below is the explanation and code bits to reproduce the error.

  1. Created a Web Forms application with pre-supplied folders & packages, configured for HTTPS
  2. In the default.aspx page added an asp:Button inside an asp:UpdatePanel which should partial post back the web form.
  3. The objective of this asp:Button is to do some business logic on the server-side (C#) and scroll to an HTML <div> on the client-side (JavaScript)
  4. Executed the application. However, it's not working as expected.

My observation is that It is scrolling to the <div> and immediately loading the form with some AJAX error.

I am not so sure where to start debugging advanced, but I would like to request somebody to help it out.

I've captured a few video bits (less than 1 min play) and screenshots. please check at the link https://1drv.ms/f/c/4f306b866deac618/EiF1VssHtEJFo7RiFlU9eSsBv_FGa1_yA4jnmS7VOdikdw?e=9wBm6l

Error images and code bits follow...

Error1

Error2

<asp:UpdatePanel ID="upd1" runat="server">
    <ContentTemplate>
        <asp:Button ID="btn1" runat="server" Text="Scroll" OnClick="btn1_Click" OnClientClick="Scroll()" />
    </ContentTemplate>
</asp:UpdatePanel>
<div style="background-color:aquamarine; height:500px;">
    
</div>
<div id="div1">
    Scrolled here
</div>
<script>
    function Scroll() {
        //debugger;
        document.getElementById("div1").scrollIntoView();
    }
</script>
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,520 questions
{count} votes

3 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 67,251 Reputation points
    2024-11-13T21:16:11.7833333+00:00

    when the UpdatePanel makes a ajax callback, the page render does not include the master page (its a partial page render), so on the postback form render there is no script control.

    also you button's onclientclick happens before the postback. so it scrolls the div, but after, the update panel replaces the content, so the scroll will be lost. you will need to tie into the update panel events and do the script after the update is complete via the javascript Sys.WebForms.PageRequestManager object:

    https://learn.microsoft.com/en-us/previous-versions/aspnet/bb386571(v=vs.100)


  2. Lan Huang-MSFT 29,911 Reputation points Microsoft Vendor
    2024-11-14T07:03:00.6166667+00:00

    Hi @Srinivas Chintamaneni,

    that's great. Can you please provide me with the source code for my knowledge? so that I Learn. Thank You.

    I used the code you provided for testing without any modification.

    https://learn.microsoft.com/en-us/answers/questions/2118431/asp-net-web-forms-error-when-javascript-function-e?comment=question#comment-1841426

    Perhaps you could create a regular aspx page to test it.

    More information:https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView

    User's image

    Test code:

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <link href="Content/bootstrap.min.css" rel="stylesheet" />
        <script>
            function Scroll() {
                //debugger;
                document.getElementById("div1").scrollIntoView();
            }
        </script>
    </head>
    <body>
        <form id="form1" runat="server">
            <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
            <asp:UpdatePanel ID="upd1" runat="server">
                <ContentTemplate>
                    <asp:Button ID="btn1" runat="server" Text="Scroll" OnClientClick="Scroll()" />
                </ContentTemplate>
            </asp:UpdatePanel>
            <div>
                <div style="background-color: aquamarine; height: 1500px;">
                </div>
                <div id="div1">
                    Scrolled here
                </div>
            </div>
        </form>
    </body>
    </html>
    

    Best regards,
    Lan Huang


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread

    0 comments No comments

  3. Albert Kallal 5,331 Reputation points
    2024-11-18T16:00:29.5366667+00:00

    Some final thoughts and a follow up.

    First up, the post-back and round trip. As noted by Bruce, we STILL have a post-back, and thus we can't run the client side code first, since if we have save this code:

            <asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
    
                <main>
    
                    <asp:UpdatePanel ID="upd1" runat="server">
                        <ContentTemplate>
                            <asp:Button ID="btn1" runat="server" 
                                Text="Scroll" 
                                OnClick="btn1_Click" 
                                OnClientClick="Scroll()"
                             />
                        </ContentTemplate>
                    </asp:UpdatePanel>
    
    
                    <div style="background-color: aquamarine; height: 500px;">
                    </div>
    
                    <div id="div1">
                        Scrolled here
                    </div>
    
                    <script>
                        function Scroll() {
                            //debugger;
                            document.getElementById("div1").scrollIntoView();
                        }
                    </script>
    
    
    
    
                </main>
    
            </asp:Content>
    
    

    Note for above, I have included the FULL page markup, only minus the page directive. (so this is a child page of master).

    Code behind:

            protected void btn1_Click(object sender, EventArgs e)
            {
                System.Threading.Thread.Sleep(2000);
    
            }
    
    

    So, what will occur? Well, the button will be clicked, the client side code will run (and scroll), and then we have the server side code wait 2 seconds, and then the WHOLE NEW fresh part of the update panel will come down the network pipe, and refresh the screen, and that will un-scroll the effects of the scroll.

    Hence, even before we run the code, we should see the page scroll(), and then un-scroll after the server side code is complete.

    And this is exactly what we expect and see:

    scrollfun

    Ok, so the suggesting (at least by me), is let's have the code run AFTER we finish the server round trip and post-back (and to be 100% clear, it is called a partial page post back when using a update panel, but it is STILL a post back, and round trip, and even the page load event fires each time before the button click server stub runs).

    So, we can remove the server side click event, and inject (run) the JavaScript code AFTER the update panel round trip to the server. However, JavaScript often runs asyncrioues, or often is threaded. That means the Scroll() function runs, but the browser UI thread and plotting is not YET quite done! So, the Scroll() function triggers, but runs before the UI threading of the browser is complete, and thus does not work!

    However, in JavaScript, there is a way to force (trick) the rendering engine to run, and when the UI threads are done, then we run pending JavaScript code. (this is a 1000 + page conept and whole books are dedicated to how this works, but suffice to say, pushing the pending code into the program stack as opposed to the UI rendering stack (browsers have both types of threads), then this all works by introduction of setTimer().

    So, now the newly updated code is thus:

    client side:

                    <asp:UpdatePanel ID="upd1" runat="server">
                        <ContentTemplate>
                            <asp:Button ID="btn1" runat="server" 
                                Text="Scroll" 
                                OnClick="btn1_Click" 
                             />
                        </ContentTemplate>
                    </asp:UpdatePanel>
    
    
                    <div style="background-color: aquamarine; height: 500px;">
                    </div>
    
                    <div id="div1">
                        Scrolled here
                    </div>
    
                    <script>
                        function Scroll() {
                            //debugger;
                            document.getElementById("div1").scrollIntoView();
                        }
                    </script>
    
    
    

    And our server side code (with script injection to run scroll after the server side code).

           protected void btn1_Click(object sender, EventArgs e)
           {
               System.Threading.Thread.Sleep(2000);
               string sJava = "setTimeout(Scroll,250);";
               ScriptManager.RegisterStartupScript(upd1, upd1.GetType(), "my code", sJava, true);
    
           }
    
    

    So, now the effect will be a 2 second wait, then the page (update panel) refresh occurres, and then we run our scroll(), but only after a delay. In fact a delay of 1 will work, since as noted, this pushed Scroll function into a stack of pending routines to run, and they do so AFTER the UI up dateing of the browser is complete (UI threads are complete).

    Hence, the result is now this:

    scrollfun2

    And if we 100% remove the delay (server side!!), the scroll function will of course still work just fine.

    So, in fact, with the update panel, we have to run the JavaScript code AFTER the update panel, since as noted, while the update panel "looks like" there is no post-back and round trip to the server, there is in fact a round trip occurring!

    However, the browser after receiving the updated content, and we inject the script? Well, the injected script does not really wait until "on page ready" for that injected code to run. Hence, there are two ways to address this issue. The above - use setTimer(), and the 2nd way would be to attached code to NOT the page "on ready", but to a event that runs AFTER the update panel, and this is also rather possible, and I can post the code on how to do this, but for now, the above setTimer looks to be a good solution.

    And this is thus not due to having bootstrap directly, but only that bootstrap puts extra UI workloads on the browser, and once again, the Scroll() code was running before the UI bits and parts are complete, and thus it looked like it was not working. So, while "sort of" the issue might be fixed by removing bootstrap, it really that the UI workloads are being increased, and thus Scroll() was running before that other threaded UI code was not completed.

    As for the script manager errors? It not at all clear why or how you were receiving as such, but we would need to see the FULL page markup used in that case - including the page header (as above shows, we did not need to add a ScriptManager to the page, since as noted, it is already in the master page).

    Regardless, adopting the above approach (script injection + setTimer()) looks to make all the moving parts work correct.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.