When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Tuesday, August 10, 2004

Understanding Pagination in ASP.NET 1.x Mobile Applications

By Jason Salas


Introduction


Even for experienced ASP.NET developers, authoring mobile Web applications can be tricky. Many of the facilities and features that make ASP.NET 1.x such a great platform on which to develop great apps are available in the mobile venue through the Microsoft Mobile Internet Toolkit (MMIT). The MMIT includes built-in features for preserving data through view state and session state, caching, and centralized configuration. However, the means by which the MMIT accomplishes these ends is not always as you might expect. The challenges presented by the MMIT are due to the very important differences between desktop Web and mobile Web platforms. It's essential for astute ASP.NET programmers to be aware of these differences and how they can affect the behavior of their applications.

One such major difference is that in a desktop-based Web browser, the end user can view all of the Web page's data at once. For mobile devices, however, there is often limited screen real estate. Cell phones, for example, might only allow a dozen lines of text to be viewed at a time. In order to send the appropriate amount of data to a mobile browser, the MMIT uses a technique known as pagination, which breaks up the returned content into correctly-sized chunks. In this article we'll examine MMIT's pagination features and how they affect mobile application development.

- continued -

Paging in Mobile Web Applications


Paging in mobile Web applications is largely variable and dependent upon the individual device and the server settings of a service provider. As an example of the former, one of my site's 15,000-character news articles may either be read entirely on a single scrollable WAP page on a smartphone, but may be paged seven times on a smaller-resolution cellular phone that can only handle 35 lines of data per screen. As an example of service provider limitations, a local cellular service provider constrains the size of content that can be sent down to the client to about 1,300 characters per virtual page.

The Importance of ViewState in Mobile Web Applications - Turn it On!


In non-mobile development, we as ASP.NET programmers are taught to disable the Page-level view state and session state by setting the EnableViewState and EnableSessionState properties to false when not explicitly necessary. By turning off view state (when not needed), we can greatly reduce the total amount of overhead and content downloaded by a client. You can also disable session state and/or view state in the Web.config file, if you know that your entire application will not need session state or view state information.

In the mobile world, view state and session state are invaluable tools a developer needs to display content. For example, view state and session state work in tandem to provide the important pagination features. That is, in developing desktop-based Web applications, view state and session state are available for providing extra functionality outside the scope of displaying information. View state is useful for remembering state changes across postbacks; session state is one way to share user-specific data across the Web application. For mobile-based applications, session state and view state play a more important role, as they are commonly used in the actual display of data.

Paginating "Large" Amounts of Data


To enable pagination for large amounts of data, you'll need to enable pagination in your mobile application. To accomplish this, set the Boolean Paginate property of the server-side <form> tag to "true". This tells the mobile page framework to determine, on its own, the best manner in which to fragment your content across post backs. When paginating content, a mobile form will display as much content as possible within a single form, and then automatically include navigation links at the bottom of the page, allowing a user to move back or forward within the form's content. The default text for said navigation links is "Next" and "Previous", but it may be modified at design-time by altering the values of the Form.PagerStyle.NextPageText and Form.PagerStyle.PreviousPageText properties.

You can also enable pagination at the control level by setting the Form.ControlToPaginate property to "true", which is good for the TextView control, which holds large amounts of content. (Note: if ControlToPaginate is set to "true" and the Form control in which it sits is set to "false", pagination will still occur.)

Working with the OnPaginate Event One of the events raised when your mobile page reloads due to automatic pagination is the OnPaginate event. You can handle custom logic within this event handler; I typically toggle the visibility of a "[HOME]" link returning to a splash page, like so:

// handle the Paginated event
protected void DisplayPageNumber(object sender,EventArgs e)
{
  linkGoHome.Visible = true;
}

Output Caching Paginated Content in Mobile Web Forms


Any savvy ASP.NET developer knows the importance of caching and how to manage/manipulate it for optimal performance, in particular applying output caching to individual pages, which ensures frequently-accessed content loads quickly without repetitive server roundtrips to a data store. Output caching caches the entire markup of the requested resource, and can be configured to store separate cache instances for different parameter values. Specifically, the @OutputCache directive's VaryByParam allows for the page developer to specify a semi-colon delimited list of parameters by which to vary the cache. (For more information on output caching, be sure to read: Caching with ASP.NET.)

There's one caveat to be aware of when using output caching with a paginated mobile form: because a mobile form may be paged many times over, output caching will cause the page to display the first virtual page of cached data repeatedly. This is because each time the request comes into the Web server for the next page of data, the Web server returns cached content, which contains the data from the first page. To solve this problem, you need to vary the cache by the requested page number, which is stored in the __EVENTARGUMENT HTTP POST header. Specifically, you must include __EVENTARGUMENT within the VaryByParam property to properly page through data while caching previously-viewed pages. It's a strange condition if you're used to wired output caching, but does work beautifully, as in the following code, which caches the paged contents of a news article within a mobile form for 10 minutes:

<%@ OutputCache Duration="600" Location="ServerAndClient" VaryByParam="__EVENTARGUMENT;OtherParameters" %>

Handling Errors Due to Expired View State


Another concern with pagination in mobile-based Web applications is expired view state, which will inevitably be a concern, and make for a nasty error when it does. With ASP.NET mobile Web forms, all data is persisted on a per-user session basis, with the hidden variable __VIEWSTATE containing only a reference to the user's specific session identifier (hence the importance of enabling session state in mobile pages, and hence the reason why view state can "expire"). By having the hidden __VIEWSTATE form field merely contain a reference to a session instance, a much smaller amount of data is passed down from the server to the client, and back again on postback.

Several things could happen that might lead to a mobile web form's view state expiring. A cellular phone's battery could die while in the middle of a browsing session, or a smartphone's owner could go outside for a smoke break and simply leave the device alone for a long period of time. These and many other situations will inevitably come into play, and any of them would force that user's session state to expire eventually.

Because a reference to the session state is held within the mobile web form's ViewState object, if the user clicked on a link within a paginated mobile page pointing to the next or previous page in the series, or tried reloading the current page with expired session state, the server would be trying to recall non-existent data. In this case, the mobile page framework would invoke the OnViewStateExpire method, throwing an exception of type System.Exception.

OnViewStateExpire can be overridden to allow for a more graceful departure from having the user be greeted by the .NET-generated error message. I typically redirect the user to a static splash page not dependent on persistent state data. This forces the user to reselect the link, but effectively reassigns the user with a new session. Your first thought as a wired Web developer might be to use the Response.Redirect() method to send the user to the static mobile page, but that method doesn't necessarily behave as expected with mobile-based applications. Instead, call Form.RedirectToMobilePage(url), passing in as an argument a string value pointing to a "safe" URL. From there the user can navigate through the pages, working under a newly-assigned session.

// override the default implementation for expired ViewState
protected override void OnViewStateExpire(EventArgs e)
{
    // do not use the base class implementation, as doing so 
    // throws an error of type "System.Exception"
    // this.Response.Redirect("http://wireless.kuam.com");
    this.RedirectToMobilePage("http://wireless.kuam.com");
}

Not your Father's Web.config File...


When creating a mobile-based Web application, I have found using the following Web.config file a good template to start with to maximize the performance of the application. I've found the sessionStateHistorySize attribute of the mobileControls node within <system.web> to be sort of misleading. You may encounter errors due to expired view state (see above), which throws an exception that implies that increasing the sessionStateHistorySize will fix. This isn't completely true - you'll need to tweak this value with the value you set for the timeout attribute in the sessionState node to get it work the way you want. Typically, I decrease the timeout attribute slightly while increasing the sessionStateHistorySize a bit.

Also, the useFullyQualifiedRedirectUrl is key. If you're using munged URLs (in which the Session.SessionID variable is included within the URL of the page being browsed, by setting the cookieLess attribute of the sessionState node to "true"), you'll want to set useFullyQualifiedRedirectUrl to "true" to allow for proper redirects without wrecking your session data.

The following is the Web.config template I use in my mobile-based application's:

<configuration>
    <system.web>
        <sessionState mode="InProc" cookieless="true" timeout="20"/>
        <mobileControls sessionStateHistorySize="45"/>
        <customErrors mode="Off"/>
        <compilation defaultLanguage="C#" debug="false"/>
        <trace enabled="false"/>
        <globalization culture="en-US" uiCulture="en-US" responseEncoding="utf-8" requestEncoding="utf-8" fileEncoding="utf-8"/>
        <pages enableSessionState="true" enableViewState="true" autoEventWireup="true"/>
        
        <!-- USE RELATIVE PATHS ONLY FOR REDIRECTS OR ELSE SESSION STATE IS LOST IN THE MUNGED URL -->
        <httpRuntime useFullyQualifiedRedirectUrl="true"/>

    </system.web>
</configuration>

Conclusion


In this article I briefly touched on some of the major considerations you'll need to mull over when creating mobile Web applications that use pagination to improve the cost of sending large amounts of data to the client. Such sources of large data can be long lists, large amounts of text, or other scenarios where you find yourself sending massive amounts of markup to the mobile client.

If you're working on an ASP.NET mobile web application for the first time, all your knowledge from your experience in doing wired applications is definitely going to help, but just be aware of the differences in importance in view state, session state and output caching. Properly managing these considerations in the wireless arena will create applications that blaze, without user discomfort due to some of the hardships wireless clients have to deal with.

For more information on this topic, check out the MMIT QuickStarts Tutorials and read Andy Wigley's & Peter Roxburgh's seminal book Building Microsoft ASP.NET Applications for Mobile Devices, Second Edition.

Happy Programming!

  • By Jason Salas


    Jason Salas is Web Development Manager for KUAM-TV in Guam, where he also is a news anchor and sports anchor. He's a Microsoft MVP for ASP.NET and founded the ASP.NET User Group of Guam. Write to Jason at jason@kuam.com.



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article