Understanding Pagination in ASP.NET 1.x Mobile ApplicationsBy Jason Salas
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.
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
EnableSessionStateproperties 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.configfile, 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
Paginateproperty 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
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
Working with the
One of the events raised when your mobile page reloads due to automatic pagination is the
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:
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
VaryByParamallows 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:
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
__VIEWSTATEcontaining 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
__VIEWSTATEform 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
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,
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.
Not your Father's
When creating a mobile-based Web application, I have found using the following
Web.configfile a good template to start with to maximize the performance of the application. I've found the
sessionStateHistorySizeattribute of the
<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
sessionStateHistorySizewill fix. This isn't completely true - you'll need to tweak this value with the value you set for the timeout attribute in the
sessionStatenode to get it work the way you want. Typically, I decrease the timeout attribute slightly while increasing 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:
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.
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 firstname.lastname@example.org.