How not to use ASP.AJAX - Pt 4

Previously I've spoken about how the ASP.NET Ajax can be used and abused. It offers a very quick and simple framework to make parts of your webpage asynchronous, mainly through use of the UpdatePanel. The tradeoff is the responsiveness of your site, and the fact that the Viewstate needs to be passed with every call. A way around the ASP.NET Ajax bloat is to use Json, which provides simple and lightweight communication with the server, at the cost of a little more complexity and loss of maintainability.

A common scenario in using ASP.NET Ajax is to put a GridView or other data based control into an update panel, with a Timer to continually poll the data. This would look something like:

<asp:UpdatePanel runat="server">

    <ContentTemplate>

        <asp:GridView runat="server" DataSource="dsSales" />

        <asp:Timer runat="server" Interval="5000" />

    </ContentTemplate>

</asp:UpdatePanel>

This is a grid that would get updated every 5 seconds.

Unfortunately, if you had 3 of these suckers on the page, or if the data source gets updated sporadically, you're going to see a big viewstate being handed back and forth every 5 seconds. Consider this chunk of HTML:

<asp:UpdatePanel runat="server" ID="upSalesWest">

    <ContentTemplate>

        <asp:GridView ID="gvSalesWest" runat="server" />

        <asp:Timer ID="timSalesWest" runat="server" Interval="5000" />

    </ContentTemplate>

</asp:UpdatePanel>

 

<asp:UpdatePanel runat="server" ID="upSalesEast">

    <ContentTemplate>

        <asp:GridView ID="gvSalesEast" runat="server" />

        <asp:Timer ID="timSalesEast" runat="server" Interval="5000" />

    </ContentTemplate>

</asp:UpdatePanel>

 

<asp:UpdatePanel runat="server" ID="upSalesNorth">

    <ContentTemplate>

        <asp:GridView ID="gvSalesNorth" runat="server" />

        <asp:Timer ID="timSalesNorth" runat="server" Interval="5000" />

    </ContentTemplate>

</asp:UpdatePanel>

The viewstate is not small. As such, you want to reduce the number of ASP.NET Ajax calls as best you can. So what can you do? Firstly, get rid of all those Timers. If you're checking for a batch of updates, you only really want to use one call. You can do this using a single call to a web service that returns the update "triggers" so to speak, that are held within the update panels:

[WebMethod]

public string[] GetUpdatedGrids()

{

    //(Based on your data sources)

    //Check the datasources bound to gvSalesWest, gvSalesEast, gvsSalesNorth

    //to see which ones contain "dirty" data (ie: which ones have

    //been updated since the data was last checked

 

    //txtSalesEast, txtSalesNorth etc are textboxes within the update panels

    //They are hidden through CSS, and automatically post back when their

    //value changes, which will cause the update of the UpdatePanel they're in

    //Unfortunately this is a hacky way to get UpdatePanels to update via javascript,

    //until MS releases something more capable.

    return new string[] { "txtSalesEast", "txtSalesNorth" };

}

To call the webservice on a timed basis, all you need to do is take advantage of javascript's SetInterval(delegate, n) function, which executes a given function every n milliseconds. With the new TextBox triggers, your modified HTML will look like:

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title>Timer Demo</title>

    <script type="text/javascript">

        function StartTimer()

        {

            SetInterval(GetUpdatedGrids, 5000);

        }

 

        function GetUpdatedGrids(result)

        {

            for(var i=0; i<result.length; i++)

                RefreshPanel(result[i]);

        }

 

        function RefreshPanel(triggerName)

        {

            //Changing the value of the textbox trigger will cause it to postback and

            //update its parent UpdatePanel

            document.getElementById(triggerName).value = new Date().getTime();

        }

    </script>

</head>

<body onload="StartTimer()">

    <form id="form1" runat="server">

        <asp:ScriptManager ID="ScriptManager1" runat="server" >

            <Services>

                <asp:ServiceReference Path="WebService.asmx" />

            </Services>

        </asp:ScriptManager>

        <div>

            <asp:UpdatePanel runat="server" ID="upSalesWest">

                <ContentTemplate>

                    <asp:GridView ID="gvSalesWest" runat="server" />

                    <asp:TextBox runat="server" ID="txtSalesWest" AutoPostBack="true" style="display:none;" />

                </ContentTemplate>

            </asp:UpdatePanel>

 

            <asp:UpdatePanel runat="server" ID="upSalesEast">

                <ContentTemplate>

                    <asp:GridView ID="gvSalesEast" runat="server" />

                    <asp:TextBox runat="server" ID="txtSalesEast" AutoPostBack="true" style="display:none;" />

                </ContentTemplate>

            </asp:UpdatePanel>

 

            <asp:UpdatePanel runat="server" ID="upSalesNorth">

                <ContentTemplate>

                    <asp:GridView ID="gvSalesNorth" runat="server" />

                    <asp:TextBox runat="server" ID="txtSalesNorth" AutoPostBack="true" style="display:none;" />

                </ContentTemplate>

            </asp:UpdatePanel>

        </div>

    </form>

</body>

</html>

One thing to note specific to this example is that it would probably want to throw a js error on RefreshPanel(), as the triggerName parameter passed to it is the ID of the control, rather than the ClientID

The whole point of this design is to use the heavy duty ASP.NET Ajax calls only to update the data. In the interim, we use lightweight Json calls to see if anything has actually been updated. For data that gets updated "every now and then", this model helps eliminate more bandwidth intensive calls through ASP.NET Ajax, which ultimately could all be for no purpose if the underlying data is still the same.

From the past few posts, I've demonstrated how we can implement Json and Web.Services as an alternative to ASP.NET Ajax, and lastly how they can work side-by-side. As I've mentioned in the past, sometimes one method is superior to the other, but that's the fun of IT - it's your call as to which one you feel is best to use.

«November»
SunMonTueWedThuFriSat
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678