Part 1 - IntroductionPart 2 - Basic ExamplePart 3 - Complex ExamplePart 4 - Final NotesBonus - Ajax History and the Memento PatternExtra Bonus - Issues with Opera
Handling Ajax history has been a critical issue since Ajax first started. With the advent of .net 3.5 the ability to easily deal with that is rolled into the code. This is part 2, here we will look at a simple example of handling Ajax history to give a basic understanding of the process. If you have not read Part 1, I suggest you do that now. Part 3 will expand on handling Ajax history when the data is more complex.For simplicity sake we are only going to look at an example of very, very basic history. We are going to look at a page that displays changes made to the time.
A basic assumption is that you are fairly familiar with Ajax (http://ajax.asp.net). We are going to be using the ScriptManager (of course) and an UpdatePanel. Our basic page looks like this
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AjaxHistory.aspx.cs" Inherits="AjaxHistory" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> <title></title></head><body> <form id="form1" runat="server"> <asp:ScriptManager runat="server" ID="sm1" EnablePartialRendering="true" /> <div> <asp:UpdatePanel runat="server" ID="upME"> <ContentTemplate> <asp:Button runat="server" ID="uxChangeTime" OnClick="uxChangeTime_Click" Text="-- change:" /> <asp:Label runat="server" ID="lblTime" /> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="uxChangeTime" EventName="Click" /> </Triggers> </asp:UpdatePanel> </div> </form></body></html>
The codebehind sets the label text to be the current date/time on every click:
(c# code)protected void uxChangeTime_Click(object sender, EventArgs e){ string _currentDateTime = DateTime.Now.ToString("F"); lblTime.Text = _currentDateTime;}
(vb code)Protected Sub uxChangeTime_Click(ByVal sender As Object, &_ ByVal e As System.EventArgs) Handles uxChangeTime.Click Dim _currentDateTime As String = DateTime.Now.ToString("F") lblTime.Text = _currentDateTimeEnd Sub
As you can see this is fairly straightforward. Clicking on the button displays the current DateTime in the label. However, there is no history. Clicking back will not display the last DateTime displayed but either be grayed out (if this was the first page loaded) or take you back to the page before this one.
To enable history is very, very simple in 3.5
The modifications are very simple - set EnableHistory equal to true and specify what should handle the Navigate event. You can also specify if you want the HistoryState to be 'secure' by setting EnableSecurityHistoryState equal to true, but this is optional.
Your ScriptManager should now look like this:
<asp:ScriptManager runat="server" ID="sm1" EnableHistory="true" OnNavigate="sm1_Navigate" EnableSecureHistoryState="true" />
<asp:UpdatePanel ...> ... <Triggers> <asp:AsyncPostBackTrigger ControlID="uxChangeTime" EventName="Click" /> <asp:AsyncPostBackTrigger ControlID="sm1" EventName="Navigate" /> </Triggers></asp:UpdatePanel>
What you are doing here is notifying the ScriptManager what information to store as a HistoryPoint by calling its AddHistoryPoint method. There are three possible overloads and we will look at the other two next blog, but for now we will use one of the simplest, a single key/value string pair to store the current DateTime with the key "myTime":
(c# code)protected void uxChangeTime_Click(object sender, EventArgs e){ string _currentDateTime = DateTime.Now.ToString("F"); lblTime.Text = _currentDateTime; ScriptManager.GetCurrent(this).AddHistoryPoint("myTime", _currentDateTime);}
(vb code)Protected Sub uxChangeTime_Click(ByVal sender As Object, &_ ByVal e As System.EventArgs) Handles uxChangeTime.Click Dim _currentDateTime As String = DateTime.Now.ToString("F") lblTime.Text = _currentDateTime ScriptManager.GetCurrent(Me).AddHistoryPoint("myTime", _currentDateTime)End Sub
In this event we retrive the State property of the HistoryEventArgs and use that to set the page to be what we want it to be. In this very simple example we will use it to set the value of the label to be the DateTime that that particular page displayed:
(c# code)protected void sm1_Navigate(object sender, HistoryEventArgs e){ string _historyValue = e.State["myTime"]; if (_historyValue != null) { lblTime.Text = _historyValue; }}
(vb code)Protected Sub sm1_Navigate(ByVal sender As Object, &_ ByVal e As System.HistoryEventArgs) Handles sm1.Navigate Dim _historyValue As String = e.State["myTime"] if(_historyValue <> Nothing) { lblTime.Text = _historyValue }End Sub
Voila! We now have a functional Ajax page with history. Try it!
What has happened is that we are using History Points. When we click the button it determines the current DateTime, displays it, and stores it as a history point. When we click the "Back" button it retrieves the previous history point (which was the current DateTime in string format) and displays that (see chart below).
Next blog: a look at more intensive use of History Points...btw, for prep, take a looksee at my blog on the Memento pattern and Ajax history to understand my basic approach: http://www.myfriedmind.com/techBlog/2009/05/20/AjaxHistoryAndTheMementoPattern.aspx
dasBlog theme by Mads Kristensen
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.