Search code examples
c#asp.nettimerupdatepanelplaceholder

How to use asp:UpdatePanel the right way?


I have a little issue with a asp:updatePanel statement. I create a html string with some sql querys in a public void and set it into a placeholder and execute this void on Page_Load. Then i have a Updatepanel with a trigging timer but when the timer triggs first time a new dublicated html string shows up at my homepage insted of updateing the one i create on page load. After that everytime the timer triggs both html strings updates.

I have also tried with asp:timer OnInit and OnLoad. My problem are still there.

Also tried to remove Machinebox from pageload then my html string waits for timer to trig first time. But i dident get any dublicates.

Does anyone have a solution for this?

ASP:

    <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" ViewStateMode="Enabled">
    <ContentTemplate>
        <asp:PlaceHolder ID = "MachineBoxHolder" runat="server" />    
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
    </Triggers>
</asp:UpdatePanel>
<asp:Timer ID="Timer1" runat="server" Interval="3000" OnTick="MachineBox_Tick">
</asp:Timer>

Pageload:

protected void Page_Load(object sender, EventArgs e)
    {
        MachineBox();
    }

Machinebox:

DataTable dt = new DataTable();

        SqlConnection connection = new SqlConnection(constr);
        connection.Open();
        SqlCommand sqlCmd = new SqlCommand("SELECT [MachineID], [MachineName], [Quality] FROM [dbo].[Machines] WHERE [Activated] = 1", connection);
        SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
        sqlDa.Fill(dt);
        if (dt.Rows.Count >= 1)
        {
            //htmlstring.
            StringBuilder html = new StringBuilder();

            //Table start.
            html.Append("<div class='row'>");

            //Bygger Data rows.
            foreach (DataRow row in dt.Rows)
            {
                SqlCommand sqlCmd1 = new SqlCommand("SELECT AVG(effectively) FROM [" + row.Field<Int32>("MachineID") + "] WHERE time >= dateadd(hh, -" + tid + ", getdate())", connection);
                tempAvailability = (Int32)sqlCmd1.ExecuteScalar();

                SqlCommand sqlCmd3 = new SqlCommand("SELECT MAX(counter) FROM [" + row.Field<Int32>("MachineID") + "] WHERE time >= dateadd(hh, -" + tid + ", getdate())", connection);
                tempMaxCounter = (Int32)sqlCmd3.ExecuteScalar();

                SqlCommand sqlCmd4 = new SqlCommand("SELECT MIN(counter) FROM [" + row.Field<Int32>("MachineID") + "] WHERE time >= dateadd(hh, -" + tid + ", getdate())", connection);
                tempMinCounter = (Int32)sqlCmd4.ExecuteScalar();

                SqlCommand sqlCmd2 = new SqlCommand("SELECT TOP (1) effectively FROM [" + row.Field<Int32>("MachineID") + "] ORDER BY time DESC", connection);
                tempState = (Int32)sqlCmd2.ExecuteScalar();

                tempPerformance = ((tempMaxCounter - tempMinCounter) / (tid * antal)) * 100;
                tempOEE = (tempAvailability * tempPerformance * row.Field<Int32>("Quality")) / 10000;

                if (tempState > 50)
                {
                  HTML CODE

                 }

            //Table slut.
            html.Append("</div>");


            //Placerar i placeholder.
            MachineBoxHolder.Controls.Add(new Literal { Text = html.ToString() });
        }

Trigger:

protected void MachineBox_Tick(object sender, EventArgs e)
    {
        MachineBox();
    }

Solution

  • I have put your code in a test page. Instead of the database query I just wrote some text to show.

    I got the same behaviour.

    Then I altered the click event:

    protected void MachineBox_Tick(object sender, EventArgs e)
    {
       // MachineBox();
    }
    

    Then I didn't get the duplicated value.

    MachineBox(); is called anyway at Page_Load and having the same in the MachineBox_Tick would execute it twice.

    As mentioned in a comment above, this should work too in the Page_Load event.

    if(!IsPostBack)
    {
        MachineBox();
    }