One of the more interesting aspects of HTML is the local storage scenario.

You always hear folks say that the hardest thing about new technologies is not learning the technology itself but rather changing the way that we think about the problems and solutions that the new technology might be appropriate for.

Using Client Side Storage (HTML5 Local Storage) definitely falls into that category.

One of the things that is somewhat unique to user expectations of web applications is that they can simply walk up to “any” web browse running on any machine and use the application as they like.

In most (ok. nearly ALL) cases this should be the case.

If so, wouldn’t client side storage be a bad idea? I mean, if I store data on the machine that the user is interacting from and then the user later access my application from a different machine, all that saved data is gone.

True. But still there are good uses for Client Side storage.

Let me propose s few…..

•Long running or multi session state. (Without adding server resource consumption.)
•Frequently used or needed data for single long running sessions (only has to be fetched ONCE for the session.)
•As a local data cache (if it’s there, use it, if not, fetch and save it.)
•User specific data like a “You’ve visited this page x number of times”.

You probably wouldn’t want to save data ONLY on the client but still there are some interesting usage scenarios.

HTML provides two different client side storage options with two different persistence scopes.

•Session – stores data that lives only for the current browsing session.
•Local – stores data even after the browser has been closed and the “session” is terminated.

Note that there are additional solutions that use browser plug-ins, but these are the “standard” facilities.

For more detail about HTML5 Web Storage you can read the W3C Specification [ HERE ]. There is also information about Microsoft’s DOM storage implementation [ HERE ].

If we are going to use local storage then the first thing that we might want do is detect browser support since if client storage is not supported we will either need to omit the feature from rendering or execute some alternate strategy for that particular feature (like a server-side equivalent.)

Here’s a sample using the Modernizr library.


<link href='~/Styles/Site.css' rel='stylesheet' type='text/css' />
<script src='Scripts/jquery-1.4.1-vsdoc.js' type='text/javascript'>
</script>
<script src='Scripts/modernizr-1.7.min.js' type='text/javascript'>
</script>
<script type='text/javascript'>
	$(function () {

		if (Modernizr.localstorage) {
			// browser supports local storage
			alert('YES - Local Storage');
		}
		else {
			// browser doesn't support local storage
			alert('NO - Local Storage');
		}

		if (Modernizr.sessionstorage) {
			// browser supports local storage
			alert('YES - Session Storage');
		}
		else {
			// browser doesn't support local storage
			alert('NO - Session Storage');
		}
	});
</script>

Since most current browsers support local storage, for the sake of simplicity I’ll omit the detection code from my sample and focus on the persistence and retrieval.

Lets suppose I have an application that consists os a multipage workflow and I wanted to add a “Scratch Pad” for users of my web application.

The first page in my application might look like this.

And another page might look like this.

Take note of the yellow highlighted areas. Notes made on the first page are automatically visible on the second page.

In fact, if you close the browser and reopen it, all of the notes will still appear.

It’s pretty simple to do. Our Default.aspx page looks like this.

Since I want their notes to survive any particular browsing sesison I’ll use “localStorage” instead of “sessionStorage”.


<%@ Page Title='Home Page' Language='C#' MasterPageFile='~/Site.master'
         AutoEventWireup='true' CodeBehind='Default.aspx.cs'
         Inherits='Html5Storage._Default' %>
<asp:Content ID='HeaderContent' runat='server' 
             ContentPlaceHolderID='HeadContent'>
    <script type='text/javascript'>
        var storage = window.localStorage;
        function SaveNotes()
        {
         storage.ScratchPad = document.getElementById('TextAreaNotes').value;
        }
    </script>
</asp:Content>
<asp:Content ID='BodyContent' runat='server' 
     ContentPlaceHolderID='MainContent'>
    <h2>DOM Storage Scripting Objects.</h2>
    <p>
    <b>window.sessionStorage</b><br />
    Session storage is designed for scenarios where the user is carrying out a
    single transaction. The sessionStorage attribute of the window object
    maintains key/value pairs for all pages loaded during the lifetime of a
    single tab (for the duration of the top-level browsing context).
    </p>
    <br />
    <p>
    <b>window.localStorage</b><br />
    The local storage mechanism spans multiple windows and persists beyond
    the current session. The localStorage attribute provides persistent
    storage areas for domains. It allows Web applications to store nearly
    10 MB of user data, such as entire documents or a user's mailbox, on
    the client for performance reasons.
    </p>
    <br />
    <hr />
    <table style='width: 100%;'>
        <tr>
            <td style='width:50%; vertical-align: top; text-align: center;
                background-color: Silver;'>
            <br /><br /><br /><br />
            Form Input 1 : <input id='Text1' type='text' /><br /><br />
            Form Input 2 : <input id='Text2' type='text' /><br /><br />
            Form Input 3 : <input id='Text3' type='text' /><br /><br />
            Form Input 4 : <input id='Text4' type='text' /><br /><br />
            Form Input 5 : <input id='Text5' type='text' /><br /><br />
            Form Input 6 : <input id='Text6' type='text' /><br /><br />
            Form Input 7 : <input id='Text7' type='text' /><br />
                <br />
                <asp:Button ID='Submit' runat='server' Text='Submit Form' />
                <br /><br />
                <asp:LinkButton ID='LinkToPage2' runat='server'
                                PostBackUrl='~/Page2.aspx'>
                   Next Page >>>
                </asp:LinkButton>
            </td>
            <td style='width:50%; text-align: center;'>
                <b>Your Notes</b><br /><br />
                <textarea id='TextAreaNotes' name='TextAreaNotes' cols='40' 
				                                                  rows='20'
                          onblur='SaveNotes()'></textarea><br />
                <br />
                <asp:Button ID='ButtonClear' runat='server' Text='Clear Notes'
                    onclick='ButtonClear_Click' 
					onclientclick='EmptyNoteStorage()' />
            </td>
        </tr>
    </table>
    <br /><br />
    <hr />
    <script type='text/javascript'>
        if (storage.ScratchPad)
        {
         document.getElementById('TextAreaNotes').value = storage.ScratchPad;
        }

        function EmptyNoteStorage()
        {
         storage.removeItem('ScratchPad');
        }
    </script>
</asp:Content>

Starting at libe 65 we have a bit of JavaScript code that will run when the page is loaded. (Though I haven’t done so here for the sake of clarity for readers not using jQuery, if you ARE using jQuery, this code goes in your .ready() event handler. If you’re not using jQuery yet – please start here http://jquery.com/.)

Line 65 checks to see if there he previously created a localStorage item named “ScratchPad” and if an item by that name exists line 67 retrieves whatever value is stored in that item and puts that value in our TextArea element (our notepad).

Note our TextArea declaration on line 53. We define an OnBlur event handler for the TextArea which calles the SaveNotes() function defined at line 7.

Every time the user enters the notes area and then leaves it (like by using the mouse to select a field, submit the form, or navigate to Page2) the SaveNotes() function is called and the contents of the TextArea are saved to localStorage (see lines 6 and 9)

In the example as written there are two scenarios where the users’s most current notes migh not be saved.

If the user adds a note and then closes the browser or uses the browser back or forward buttons the OnBlur event won’t be called. If this is problematic for you, you could define a JavaScript OnOnload() event handler and call the SaveNotes() function from there to save any note the user might have added before exiting the page.

The functional code in the second page is the same as the code above.

Page2.aspx is as follows.


<%@ Page Title='' Language='C#' MasterPageFile='~/Site.Master' 
         AutoEventWireup='true'
         CodeBehind='Page2.aspx.cs' Inherits='Html5Storage.Page2' %>
<asp:Content ID='HeaderContent' runat='server' 
             ContentPlaceHolderID='HeadContent'>
<script type='text/javascript'>
	var storage = window.localStorage;
	function SaveNotes() {
		storage.ScratchPad = document.getElementById('TextAreaNotes').value;
	}
</script>
</asp:Content>
<asp:Content ID='BodyContent' runat='server' 
             ContentPlaceHolderID='MainContent'>
    <h2>DOM Storage Scripting Objects.</h2>
    <p>
    <b>window.sessionStorage</b><br />
    Session storage is designed for scenarios where the user is carrying out a
    single transaction. The sessionStorage attribute of the window object
    maintains key/value pairs for all pages loaded during the lifetime of a
    single tab (for the duration of the top-level browsing context).
    </p>
    <br />
    <p>
    <b>window.localStorage</b><br />
    The local storage mechanism spans multiple windows and persists beyond
    the current session. The localStorage attribute provides persistent
    storage areas for domains. It allows Web applications to store nearly
    10 MB of user data, such as entire documents or a user's mailbox, on
    the client for performance reasons.
    </p>
    <br />
    <hr />
    <table style='width: 100%;'>
	<tr>
	<td style='width:50%; vertical-align: top; text-align: center;
		background-color: Silver;'>
	<br />
	Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce molestie
	consectetur consequat. Donec mattis velit et mauris sollicitudin ut
	rhoncus est volutpat. Praesent vestibulum dolor lorem. Maecenas eget
	dolor libero. Class aptent taciti sociosqu ad litora torquent per
	conubia nostra, per inceptos himenaeos. Maecenas ut urna nibh, ut semper
	dolor. Ut vitae dignissim enim. Nulla facilisi. Suspendisse viverra
	aliquet bibendum. Nullam velit eros, molestie ut sagittis quis,
	condimentum vitae orci. Sed venenatis porttitor tempus. Donec id augue
	dui. Nunc sit amet risus quam, et pulvinar magna. Phasellus elementum
	imperdiet ipsum sit amet convallis. Cras purus arcu, aliquet a ultrices
	eget, aliquam et ligula. Aliquam ut egestas quam. Phasellus ipsum diam,
	ultricies ac tempus nec, porttitor at arcu. Integer ac nulla elit.
	Nunc faucibus tincidunt risus, at gravida risus pulvinar id. Donec
	non ligula at neque faucibus hendrerit.
	<br /><br />
	Curabitur congue, neque quis vehicula gravida, metus eros rutrum enim,
	non adipiscing leo nisl sit amet mauris. Suspendisse sem nulla, faucibus
	sed feugiat et, laoreet consectetur sapien. Aliquam at est quis nulla
	semper porta nec nec magna. Fusce viverra cursus ligula. Duis vestibulum
	tincidunt erat, non rutrum quam blandit in. Cum sociis natoque penatibus
	et magnis dis parturient montes, nascetur ridiculus mus. Vivamus ac
	risus at leo condimentum adipiscing. Etiam ac orci eros, nec feugiat dui.
	Vivamus nec mauris in est viverra congue at ut ante. Mauris pulvinar
	lacinia orci, eu tristique eros venenatis vitae. Donec ipsum arcu,
	faucibus a vulputate ultricies, venenatis a ipsum.
	Pellentesque ullamcorper augue sapien. In lacinia placerat scelerisque.
	<br /><br />
	<asp:LinkButton ID='LinkToPage2' runat='server' 
	     PostBackUrl='~/Default.aspx'>
	   <<< First Page
	 </asp:LinkButton>
	</td>
	<td style='width:50%; text-align: center;'>
		<b>Your Notes</b><br /><br />
		<textarea id='TextAreaNotes' name='TextAreaNotes' cols='40' rows='20'
				  onblur='SaveNotes()'></textarea><br />
		<br />
		<asp:Button ID='ButtonClear' runat='server' Text='Clear Notes'
			onclick='ButtonClear_Click' onclientclick='EmptyNoteStorage()' />
	</td>
        </tr>
    </table>
    <br /><br />
    <hr />
    <script type='text/javascript'>
	if (storage.ScratchPad) {
		document.getElementById('TextAreaNotes').value = storage.ScratchPad;
	}

	function EmptyNoteStorage() {
		storage.removeItem('ScratchPad');
	}
    </script>
</asp:Content>

The pages also contain a button that lets you empty out the Scratch Pad. See line 79, the EmptyNoteStorage() function.

Note that the “Scratch Pad” is entirely client side using JavaScript and HTML Elements.

You could add a server side persistance feature by converting the HTML elements to ASP.NET Server Controls and fetching and storing the user’s notes in code behind.

You can download a working sample [ HERE ].