Problem

Typically, the user interface in Web Applications is composed of multiple pages. Now with the increasing popularity of AJAX, it is common that people want to develop Web applications that are similar and provide the same user experience as desktop applications. One common problem in Web applications is the constant page reloads and flickering when navigating the application.

Disclaimer: We are writing this documentation as part of the new Web Client Guidance that is being done in patterns & practices. We are close to finishing this project, so I would like to get more feedback or validation from everyone that gets the chance to read this before we release. Have in mind that the content of this topic can change both in content and in form (it can change because of YOUR feedback).

Forces

Any of the following conditions suggest using the solution described in this pattern:

  • You want to minimize the page reloads and flickering when navigating through the application.
  • You want to change only the content of the page and maintain the general layout; that is the header, footer, and menus, when updating the page.
  • You want the user to keep the context of most of the page, while only manipulating the data on part of the page.
  • You want to have long running processes and/or avoid losing/refreshing dynamic content state while navigating (for example, uploading files or a chat window).
  • You want to improve the user experience of Web applications, by simulating the look and feel, and usability of desktop applications.

Solution

Have all of your page features, or at least most of them, in a single page. This is known as the Single-Page Interface (SPI) model. In the SPI model, all browser interactions with a Web application occur inside the boundaries of one page.

The SPI pattern improves the UI navigability of Web applications because it decreases the number of page reloads and eliminates flickering.

The SPI model requires a number of highly interactive features, which include in-place editing, context-sensitive user interface, immediate user feedback prompts, and asynchronous operations.

The Single-page Interface pattern elements

image

 

SPI is an AJAX pattern that suggests you have only a main page in your Web Application. This page interface is rearranged as a result of user interaction with the application.

Having a single-page interface, may result in your application using less-distinct URLs. Therefore, this pattern may not provide good support for search engines, unless explicit mechanisms for also allowing the navigation of the site by using full redirects are implemented.

Liabilities

The Single-page Interface pattern has the following liabilities:

  • As all interactions occur within a page, there are less distinct URLs. Therefore, this pattern does not inherently provide good support for search engines
  • You need to implement a mechanism to identify the different states of the application; this is for providing history browsing support and bookmarking. It might be used also for supporting permanent link. Unique URLs and deep linking can be supported in an SPI app but with additional development cost. Web applications built using more traditional full page refreshes support unique URLs and deep linking more easily.
  • You have to be careful with memory leaks, because as the page is not refreshed as often, the memory is not cleaned automatically by the browser. Therefore you have to manually dispose objects, handlers, and so on, when navigating through the page.
  • The SPI pattern requires a lot of JavaScript. If JavaScript is turned off, the user will not be able to use the application. This then requires down-level support in addition to the SPI pattern. It makes more sense to implement the SPI pattern if you have more control of your browsers, for example, if you have an intranet application and you know the corporate image does not restrict JavaScript, then SPI might work here. For the Internet case, it is more mixed because some users will enable JavaScript and some will not.
  • Consider using the Progressive Enhancement or Graceful Degradation pattern, for addressing accessibility, browsers where JavaScript is disabled, and search engine optimization. Otherwise older browsers or readers will not be able to use your application. If you choose to support accessing the website without the use of JavaScript, the complexity of the application increases exponentially, as you would typically need to create server and client side version of most of the views. This approach can also help to add better support for search engines.

Identifying the State of an Application with Distinct URLs

When using AJAX and the SPI pattern, an application may perform different operations, and therefore pass through different states while the URL in the browser stays constant. This creates the need of a mechanism to identify different states of the application, for example, for moving back to a previous state.

Browsers implement the Back and Forward buttons functionality by caching the list of visited URLs.

In AJAX, the server communication is done through XMLHttpRequests, and these requests do not change the page URL. Therefore, the list of visited URLs is not modified.

The Unique URLs pattern helps addressing this problem, by assigning a unique and expressive URL to each significant application state.

Scripting does not provide a mechanism to modify the list of visited URLs, but it provides mechanisms to modify the URLs.

You can manipulate the URL with JavaScript using the window.location.href property, but this will trigger a page reload; fortunately you can use the window.location.hash property. The hash property is used for fragment identifiers, which are optional components of URLs that came after the hash character (#). The string that comes after the hash character is not sent to the server; therefore, the browser is responsible for restoring the state through client scripts, and retrieving the appropriate views. Because they are like normal links, but within a single page, no page reload occurs, and the browser behaves as if you have clicked a standard link, adding the URLs to the list of visited URLs. This also enables history navigation, bookmarking and sharing URLs with other people.

Note: Setting the hash property does not work reliably on all browsers, and you do not get change notifications on all browsers either. For this reason, it is recommended using some library that handles these differences in a cross-browser way, such as the Microsoft Ajax Library History control.

Therefore, when there is an important state change in your application, modify the URL hash property. In this way the changes will be tracked by the browser.

JavaScript
window.location.hash = stateData;

The resulting URL will look like the following.

URL
http://www.mycompany.com/mypage.aspx#someState

Once you have identified each relevant state of the application, you need to implement code to parse the URL. You can choose the format based on your specific needs to represent a state, you can even add parameters in the URL, as seen in the following example.

URL
http://www.mycompany.com/mypage.aspx#viewProduct=5529

Finally, after parsing the URL, you should restore the application to the corresponding state based on the hash data, keep in mind that the hash data is not sent to the server as part of the URL. In the previous example, when loading that URL, the application should go to the product details form, showing the details of the product with ID 5529.

More Information

For more information about the Single-Page Interface pattern, see the following:

For more information about software design patterns applied in the Web Client Guidance, see Patterns in the Web Client Guidance.

You can find this and many other topics and key decisions for creating web client applications (both in ASP.NET Web Forms and ASP.NET MVC) in our latest Web Client Guidance drops. We are close to finishing this guidance, so your prompt feedback is invaluable to us. Make sure you check it out and comment in this topic or in the codeplex forums (there is a special tag to mark conversations for this new guidance).

kick it on DotNetKicks.com Shout it

  • Mike

    Great read, but just to be sure, what are some current usages of this pattern in the web?

  • jdominguez

    Facebook is a great example of a public site that does this. Look at the URL, that only changes the #, that’s why you can keep on chatting while you navigate. The neat thing, is that if you copy and paste this “client” URL, you will get redirected to the server version of that state, so bookmarking works correctly.
    Other good examples are OWA (Outlook Web Access) and GMail.

  • Damian Schenkelman

    Hi Julian,
    You mentioned a couple of times that as all interactions occur within a page, there are less distinct URLs. Therefore, this pattern does not inherently provide good support for search engines.

    Is this such a big liability that deserves to be mentioned twice? Anyways, perhaps it’s not such a good idea to have this in the “solution” section.

    Thanks,
    Damian

  • jdominguez

    Thanks for the feedback, you are right. I updated the docs in the guidance itself.

  • http://www.itsnat.org jmarranz

    Hola Julian
    I’ve found your blog doing some Googling about Single Page Interface, and is funny I’ve written about this subject in “The Single Page Interface Manifesto” some days ago, it shares some things.

    Current version is in Spanish.

    http://itsnat.sourceforge.net/php/spim/spi_manifesto_es.php

    Enjoy