Create Persistent ID Cookies

Also, build pageable DataGrids and run ASP.NET 1.0 and 1.1 side by side.

Jeff Prosise

October 30, 2009

8 Min Read
ITPro Today logo

AskthePRO

LANGUAGES: C#

ASP.NET VERSIONS: 1.0 | 1.1

 

Create Persistent ID Cookies

Also, build pageable DataGrids and run ASP.NET 1.0 and1.1 side by side.

 

By Jeff Prosise

 

Q: Can ASP.NET be configured to issue persistent sessionID cookies? It issues temporary session ID cookies by default, meaning sessionstate is lost when the browser is closed. I'd like to mimic the behavior ofAmazon.com, which lets me close the browser and still see the contents of myshopping cart if I come back a week later.

 

A: ASP.NET lacks a simple configuration directivecommanding it to issue persistent session ID cookies, but you can use a customHTTP module to convert temporary session ID cookies into persistent ones (seeFigure 1).

 

using System;

using System.Web;

 

public class PersistentSessionModule :IHttpModule

{

    public void Init (HttpApplication application)

    {

        application.EndRequest +=

            new EventHandler (OnEndRequest);

    }

 

    public void Dispose () {}

 

    void OnEndRequest (Object sender, EventArgs e)

    {

        HttpCookie cookie =

            HttpContext.Current.Response.Cookies

             ["ASP.NET_SessionId"];

        if (cookie != null)

            cookie.Expires = DateTime.Now.AddDays (7);

    }

}

Figure 1. This HTTP module turns temporary ASP.NET session IDcookies into persistent ones.

 

An HTTP module is an object that sits in ASP.NET's HTTPpipeline and sees all incoming requests and outgoing responses. By registeringto handle events fired from the pipeline, a custom HTTP module can hook intoASP.NET's request-processing plumbing and effect changes by modifying HTTPrequests and responses as they pass through.

 

The module in Figure 1 registers a handler for EndRequestevents - the very last event that fires before a fully formed HTTP responsegoes back to the client. The event handler checks each outgoing response for acookie containing an ASP.NET session ID. If it finds that cookie in theresponse's Cookies collection, OnEndRequest converts the cookie into apersistent cookie by setting the cookie's Expires property to a date seven dayshence. Now you can close the browser without losing your session state becausethe browser caches the cookie on the host machine's hard disk.

 

HTTP modules must be registered so they can be loaded byASP.NET each time the host application starts up. The Web.config file in Figure2 registers the HTTP module in Figure 1.

 

type="PersistentSessionModule,PersistentSessionModule" />

Figure 2. Afteryou copy the compiled HTTP module into the application root's bin subdirectory,use this Web.config file to register it.

 

To deploy the module, first compile the source code inFigure 1 into a DLL named PersistentSessionModule.dll with the followingcommand:

 

csc /t:library PersisentSessionModule.cs

 

Then move PersistentSessionModule.dll into the applicationroot's bin subdirectory, and finish up by dropping Web.config into theapplication root.

 

If you extend the lifetime of ASP.NET session ID cookiesto seven days, you'll need to extend session time-outs likewise. Otherwise, thecookie containing the session ID will hang around, but the session that itrefers to will not. That's why the Web.config file in Figure 2 contains a element setting the session time-out to 10080 minutes, orseven days.

 

Also, be aware that increased session time-outs placegreater demand on your session state store. If you store session state in a SQLServer database for a week at a time on a highly trafficked site, the databasecould grow quite large indeed!

 

Finally, note that Figure 1's OnEndRequest handler canoptionally be placed in a Global.asax file rather than an HTTP module. Simplycopy the code into Global.asax, rename the handler Application_EndRequest, andpresto! You now have persistent session cookies.

 

Q: How much flexibility do I have in customizing thenavigation bar that appears at the bottom of a pageable DataGrid? For example,how do I display the current page number between the left and right arrows? CanI also include double arrows that navigate to the first and last page?

 

A: You have infinite flexibility when modifying aDataGrid's page navigation bar (more commonly known as a pager). As long aswhat you want to display can be expressed in HTML, you can make it appear in apager.

 

I've included a figure that shows a DataGrid with exactlythe attributes you describe (see Figure 3). It even includes tooltips thatappear when the user pauses the cursor over a pager arrow. The DataGrid ishosted in a page called CustomPager.aspx (for excerpts see Figures 4 and 5).

 


Figure 3. This DataGrid uses acustom pager that displays the current page number between left and rightarrows as well as left and right double arrows.

 

Figure 4 shows how the DataGrid is declared in the ASPXfile. Pay particular attention to the Font-Name, PrevPageText, and NextPageTextattributes in the PagerStyle tag. Font-Name changes the pager's default font toWebdings. PrevPageText and NextPageText specify the Webdings character codesfor the pager's arrows, producing the stylized left and right single arrowsseen in Figure 3. This is a trick I learned from my good pal and fellow asp.netPROcolumnist Dino Esposito, known to many simply as "Mr. DataGrid."

 

  Font-Name="Verdana" Font-Size="8pt"RunAt="server"

  Width="100%" AllowPaging="true"PageSize="16"

  Gridlines="vertical" OnPageIndexChanged="OnNewPage"

  OnItemCreated="OnCustomizePager">

      DataField="productid"

      ItemStyle-HorizontalAlign="center" />

      DataField="productname" />

      DataField="unitsinstock" />

    Font-Bold="true" HorizontalAlign="center" />

    Font-Name="Webdings" PrevPageText="3"NextPageText="4"

    HorizontalAlign="center" />

Figure4. In this DataGrid declaration, the PagerStyle element creates left and right-pointingnavigation arrows, while the OnItemCreated attribute provides a hook forfurther customizations (an excerpt from CustomPager.aspx).

 

Additional pager customizations are appliedprogrammatically using the OnCustomizePager method in Figure 5, which fires inresponse to the DataGrid's ItemCreated events. OnCustomizePager's job isthreefold: It adds double arrows, applies tooltips to all the arrows, and addstext showing the current page number. The method is accompanied by theOnGotoFirst and OnGotoLast methods, which navigate to the first and last page,respectively, when a user clicks on the double arrows. The double arrows arenothing more than LinkButton or Label controls; the LinkButtons are for activearrows and the Labels are for inactive ones. An arrow is "inactive" if itpoints left and the first page is currently displayed, or if it points rightand the last page is currently displayed.

 

void OnCustomizePager (Object sender,

    DataGridItemEventArgs e)

{

    if (e.Item.ItemType == ListItemType.Pager) {

        DataGrid grid = (DataGrid) sender;

        TableCell pager = e.Item.Cells[0];

 

        // Add a double left arrow

        if (grid.CurrentPageIndex == 0) {

            Label label = new Label ();

            label.Font.Name = "Webdings";

            label.Font.Size = grid.PagerStyle.Font.Size;

            label.ForeColor = grid.PagerStyle.ForeColor;

            label.Text = "7";

            pager.Controls.AddAt (0, label);

        }

        else {

            LinkButton button = new LinkButton ();

            button.Click += new EventHandler (OnGotoFirst);

            button.Font.Name = "Webdings";

            button.Font.Size = grid.PagerStyle.Font.Size;

            button.ForeColor = grid.PagerStyle.ForeColor;

            button.Text = "7";

            button.ToolTip = "Go to page 1";

            pager.Controls.AddAt (0, button);

        }

 

        // Add a tooltip to the single left arrow

        if (grid.CurrentPageIndex != 0) {

            WebControl control =

                 (WebControl) pager.Controls[1];

            control.ToolTip = String.Format

                 ("Go to page {0}",grid.CurrentPageIndex);

        }

 

        // Add a page number between arrows

        Label indicator = new Label ();

        indicator.Font.Name = "Verdana";

        indicator.Font.Size = grid.PagerStyle.Font.Size;

        indicator.ForeColor = grid.PagerStyle.ForeColor;

        indicator.Font.Bold = true;

        indicator.Text = String.Format ("Page {0}",

            grid.CurrentPageIndex + 1);

         pager.Controls.AddAt (2, indicator);

          ...

    }

}

 

void OnGotoFirst (Object sender, EventArgse)

{

    MyDataGrid.CurrentPageIndex = 0;

    BindDataGrid ();

}

 

void OnGotoLast (Object sender, EventArgse)

{

    MyDataGrid.CurrentPageIndex =

        MyDataGrid.PageCount - 1;

    BindDataGrid ();

}

Figure5. OnCustomizePager fires in response to ItemCreated events and customizesthe DataGrid's pager (an excerpt from CustomPager.aspx).

 

This sample is merely the tip of the iceberg when it comesto pager customizations. Remember, your only constraints are those inherent toHTML. Other than that, the possibilities are endless.

 

Q: Can ASP.NET 1.0 and 1.1 run side by side? More to thepoint, is it possible to run some ASP.NET apps under version 1.1 and othersunder version 1.0 on the same Web server? And can an applicationprogrammatically determine the version of ASP.NET that hosts it?

 

A: Yes, yes, and yes. That was easy, wasn't it? Seriously,though, ASP.NET 1.0 and 1.1 coexist very well on the same server. You'll findhelpful information at www.asp.net/faq/SideBySide.aspx.Here, however, is a synopsis.

 

By default, installing version 1.1 of the .NET Frameworkconfigures existing ASP.NET applications to use ASP.NET 1.1. You can revert aspecific application to ASP.NET 1.0 by changing the version of Aspnet_isapi.dllthat the application is mapped to in the IIS metabase from 1.1.4322 to1.0.3705. The easy way to do that is to run the Aspnet_regiis utility thatcomes with version 1.0 of the .NET Framework. This Aspnet_regiis commandconfigures the application in the MyApp virtual directory to use ASP.NET 1.0:

 

Aspnet_regiis -snw3svc/1/root/myapp

 

If you decide later to migrate the application to ASP.NET 1.1,simply repeat the command, but use the Aspnet_regiis utility that comes withversion 1.1 this time.

 

As for detecting the ASP.NET version at run time, the codein Figure 6 contains the source for a page that does just that.

 

 

</p> <p>void Page_Load (Object sender, EventArgse)</p> <p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp;Output.Text = String.Format (</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"This page is using ASP.NET {0}.{1}",</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Environment.Version.Major,</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Environment.Version.Minor</p><p>&nbsp;&nbsp;&nbsp;&nbsp;);</p><p>}</p><p>

Figure6. This page displays the version of ASP.NET that hosts it.

 

It uses the Framework's static Environment.Versionproperty to grab the major and minor version numbers. Should you need them, buildand revision numbers are also present in the System.Version object theproperty's get accessor returns.

 

The sample code in thisarticle is available for download.

 

JeffProsise is the author of several books, including Programming Microsoft .NET (MicrosoftPress, 2002). He's also a cofounder of Wintellect (http://www.wintellect.com), a softwareconsulting and education firm that specializes in .NET. Have a question forthis column? Submit queries to [email protected].

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like