Archive for the ‘ASP’ Category.

Asp .net ViewState can be evil

My friend was telling me about how evil ViewState can be when dealing with ASP pages. As I’m new to the .net version of ASP pages I went investigating a little further. Taking a look at my sample two posts ago. Sure enough I’m guilty as charged, it turns out that the state of your controls in your ASP pages is automatically put into the ViewState bucket. In other words if you have large controls with a lot of data such as grids or lists your ViewState will include all of that data held by the control. With that said all of the data will travel between your server and the client on all round trips. It is a big waste of bandwidth.

At first I started up Fiddler which allows you to see the real http data transferred. If you do not yet have Fiddler in your toolbox you should check it out, it’s a great tool. However it doesn’t allow you to examine the ViewState in detail as the tool is more generic.

I did the google and came up on another tool, ViewState Helper Viewer it does exactly what I needed. It shows you the size of your ViewState and further you can drill down on it with a double click which will break the ViewState down into the variables that it’s holding, good job by the author Jon Tackabury. Jon has actually a couple of other impressive tools. As I’m writing this I realize that Jon already wrote ViewState plugin for Fiddler, which is great, I have to check that out.

So let’s take a closer look at the webpage, as seen in the viewer
viewstate2

As you can see at first on the highlighted row, the size of the ViewState is substantial. It is about 31% of the whole page, 15K of worthless data traveling to and from the client on each roundtrip, not good. In order to cut down on the size, simply add an attribute to your control in the html code, EnableViewState=”false”. This will instruct ASP .net not to include the state / data of the control in the ViewState bucket. As I applied that to the grid control you can see the next line above shows much better results than before. Then I further applied it to other controls on the page and now we are down to 456 bytes from 15,184.

If you want to read in depth analyzes of the ViewState and how it works in .net you might want to wander over here. For most pages you might just have to set the EnableViewState attribute on your controls, but for more advanced cases you might have to drill down further.

Sean thanks for being the devils advocate.

C# collection in GridView ASP page

I had the need to display a sortable GridView in an Asp page. I have a collection of objects rather than a table object. What I chose to do was to convert the collection into DataView. Then it’s easy to use the built in .net sorting. The collection updates in real time, therefor a timer was added to update the grid every 15 seconds.

First the asp code

<asp:ScriptManager ID=“ScriptManager1″ runat=“server” />
         <div>
            <asp:Timer ID=“Timer1″ OnTick=“Timer1_Tick” runat=“server” Interval=“15000″>
            </asp:Timer>
        </div>
     <table>
            <tr>
                <td>
                    <asp:Label ID=“HeaderLabel” runat=“server” Text=“” />
                    <Triggers>
                            <br />
                            <asp:AsyncPostBackTrigger ControlID=“Timer1″ EventName=“Tick” />
                    </Triggers>
                    <asp:GridView ID=“gvCarGrid”
                                SkinID=“GridView”
                                  CaptionAlign=“Top”
                                  runat=“server”
                                  Font-Size=“Small”
                                  onrowdatabound=“gvCarGrid_RowDataBound”
                                  AllowSorting=“True”
                                  onsorting=“gvCarGrid_Sorting”
                                  > 
                        <Columns>
                            <asp:BoundField ReadOnly=“true” HeaderText=“Model” DataField=“Model”
                                SortExpression=“Model” />
                            <asp:BoundField ReadOnly=“true” HeaderText=“Year” DataField=“Year”
                                SortExpression=“Year” />
                            </asp:BoundField>
                        </Columns>                                         
                    </asp:GridView>
                </td>
            </tr>
       </table>

Then the C# code

private static DataTable mCarTable = new DataTable();
        //
        private const string COL_MODEL = “Model”;
        private const string COL_YEAR  = “Year”;
        //
        private const string ASCENDING = ” ASC”;
        private const string DESCENDING = ” DESC”;
        //
        private const string SORT_ORDER = “sortOrder”;
        private const string SORT_COLUMN = “sortCol”;
       

        protected void Page_Load(object sender, EventArgs e)
        {
           
            if (!Page.IsPostBack)
            {
                // State variables
                ViewState[SORT_ORDER] = ASCENDING;
                ViewState[SORT_COLUMN] = COL_MODEL;
                // Intialize
                this.InitTable();
                // Load the grid
                this.loadGrid();
            }
        }

        // Initialize car table to use with the view
        void InitTable()
        {
            mCarTable = new DataTable();
            mCarTable.Columns.Add(COL_MODEL);
            mCarTable.Columns.Add(COL_YEAR, typeof(int));
        }

        // Initialize DataView from list
        private DataView getDataView( IList<Car> plCars )
        {
            mCarTable.Rows.Clear();

            foreach (Car  myCar in plCars )
            {
                DataRow newRow = mCarTable.NewRow();
                //
                newRow[COL_MODEL] = myCar.Model;
                newRow[COL_YEAR] = myCar.Year;
                //
                mCarTable.Rows.Add(newRow);
            }

            return new DataView(mCarTable);
        }

        void loadGrid()
        {
                IList<Car> list = getCarList();
                //
                this.addSortIndicator();
                //
                DataView carView = this.getDataView(list);
                carView.Sort = ViewState[SORT_COLUMN].ToString() + ViewState[SORT_ORDER].ToString();
                //
                gvCarGrid.DataSource = carView;
                gvCarGrid.DataBind();
        }

        // Call before sorting
        protected void gvCarGrid_Sorting(object sender, GridViewSortEventArgs e)
        {
            // Set the correct direction
            if( ViewState[SORT_COLUMN].ToString() == e.SortExpression &&
            ViewState[SORT_ORDER].ToString() == ASCENDING )
                ViewState[SORT_ORDER] = DESCENDING;
            else
                ViewState[SORT_ORDER] = ASCENDING;

            // Set it
            ViewState[SORT_COLUMN] = e.SortExpression;

            // Load it
            this.loadGrid();
        }

        private void addSortIndicator()
        {
            int iCount = 0;
            // Search for the columm with the sort expression
            foreach (DataControlField field in this.gvCarGrid.Columns )
            {
                // Reset the headers first
                field.HeaderText = mCarTable.Columns[iCount++].ColumnName;

                if (field.SortExpression == ViewState[SORT_COLUMN].ToString())
                {
                    // Add indicator to header column
                    if (ViewState[SORT_ORDER].ToString() == ASCENDING)
                        field.HeaderText += CxUtil.ASCENDING_ARROW;
                    else
                        field.HeaderText += CxUtil.DESCENDING_ARROW;
                }
            }

        }

        protected void Timer1_Tick(object sender, EventArgs e)
        {
            this.loadGrid();
        }