Thursday, May 18, 2006

Asp.net 2.0 Profiling - Auto Saving Form Data

-->

Microsoft has extended the standard web state persistence models with the addition of profiling in the ASP.NET 2.0 framework. Essentially using profiling is identical to using the HttpSession, the difference is that user data is persisted between site visits. By using the Profile, a website is able to save and retrieve persisted user data regardless of the user's browser / session / machine state. We are now able to persist user specific data (i.e. session information) between site visits without needing to write a data abstraction layer (db interface).

In other words, we can save session related information between sessions. Ignoring all the extra ASP.NET 2.0 Framework bells and whistles, an obvious use for Profiling would be found in UI design; saving and repopulating the entered data of Form input controls (i.e. Textbox) between a user's visits. One use for this sort of functionality would be remembering a User’s previous search in search pages. Another use would be to temporarily save a User’s progress through larger form based work processes (i.e. completing an online survey). This way, should the User’s Session be interrupted (i.e. browser crash), the User can continue data entry from where they last left off the next time they log onto your Site. User form data is automatically saved on postback without the need for special persistence code.


The example code (github : https://github.com/benkitzelman/ProfilePersistence) demonstrates how to construct a custom Profile responsible for transparently saving and restoring registered control values on Page loading.


By looking at PROFILE.CS we can see that it inherits System.Web.Profile.ProfileBase. It contains a public method ‘Register’ which takes a System.Web.UI.Control as one of its parameters. Register is responsible for persisting a passed control’s property to the profile, and registering it for repopulation on the next postback. The second parameter is a string defining a property name with which to bind to (i.e. when registering a TextBox, we could bind the “Text” property). Using the given control’s Page property, event handlers are assigned to the parent page’s Pre Render and Pre Loading events. Note that within the PreLoading event handler, profiled data is only loaded into the target control on the first load (Page.IsPostBack == false) preventing any overwriting of entered data between postbacks (ViewState).


The Profile manages a collection of UrlProfiles. Essentially a UrlProfile is a Serializable object (data container) responsible for managing profile data for a particular url. It is also responsible for managing the profiled data for registered controls within its Target Page.


The UrlProfile was implemented in preference of a Page Profile as quite often a page functionality can be quite varied depending on its Url (address + query string parameters). Each registered control has a ControlProfile constructed.


Ideally the reading / populating of target controls should be abstracted, requiring as little handling code as possible. Looking at PROFILETEST.ASPX, we can see that only one line of code at initialization is required to register a control for Profile persistence.



protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Profile.Register(testBox, "Text");
}
The only thing remaining is to hook up the custom profile in the website's web.config specifying a default profile provider (see Custom Persistence Layer below):

Custom Persistence Layer
By using a provider model, how this data is persisted is highly configurable. The standard (implicit) provider is the SQLProfileProvider (all data is serialized and stored to db). One can however, inherit the System.Web.Profile.ProfileProvider base class and assume control of the data persistance In the example code, the TEXTFILEPROFILEPROVIDER.CS serializes User data to a text file. This implementation is based heavily on the MSDN Example.