This project is read-only.

Crumb Trail

A common Web navigational aid is a Crumb Trail – a set of links (Crumbs) indicating the path taken by a user as they browse a site, providing the ability to return to any of these previous pages. For example, to purchase car insurance online the first screen might be personal details, the next car details and then licence details. On the car details page there would be a link back to the personal details and on the licence details page there would be two links, one to return to the car details and the other to go directly back to the personal details.

Taking the State Information configured State Information, an example route taken by the user could be starting at Dialog, D1, and Navigating along Transition T1 and then T2 described by:

D1-S1 -> D1-S2 -> D1-S3
The image below shows this Navigation, with the strong arrows being the forward Navigations along the Transitions and the dashed arrows being the desired Crumb Trail backward Navigation.

Desired Crumb Trail backward Navigation

To be able to Navigate along the dashed arrows using forward Navigation only would require three new Transitions to be added to the configuration as shown below. Such configuration would soon become unmanageable, so a better solution is required.

<dialog key="D1" initial="S1" path="~/Default.aspx">
	<state key="S1" page="~/P1.aspx">
		<transition key="T1" to="S2"/>
	</state>
	<state key="S2" page="~/P2.aspx">
		<transition key="T2" to="S3"/>
		<transition key="T1_Back" to="S1"/>
	</state>
	<state key="S3" page="~/P3.aspx">
		<transition key="T2_Back" to="S2"/>
		<transition key="T1_T2_Back" to="S1"/>
	</state>
</dialog>

The Framework, as Navigations occur, keeps track of each State passed through and hence builds a Crumb Trail. Navigation to any of these previous States is possible, without the addition of any Transition configuration. This is considered backward Navigation and to perform this there are two methods on the StateController class, called NavigateBack and GetNavigationBackLink. Each method requires a distance parameter indicating how far to return - a distance of 1 will return to the previous Crumb, 2 the previous but one Crumb etc. So to return to S1 from S3, in the example above, the distance parameter would be 2.

Analogously to their forward counterparts, for Redirecting and Transferring the method required is NavigateBack, an overload of which accepts a NavigationMode parameter which specifies whether to Redirect or Transfer (the default is Redirect); and for a Hyperlink the method is GetNavigationBackLink. A Crumbs property on the StateController class provides read-only access to a list of Crumbs, each of which contains the NavigationLink required to Navigate back to that State.

To delve into more detail about how this Crumb Trail is built, consider again the Crumb Trail below taken from the State Information configured in State Information:

D1-S1 -> D1-S2 -> D1-S3
For clarity the current State, D1-S3, is shown although the list of Crumbs on the StateController would only include D1-S1 and D1-S2. If the Crumb Trail was additive only, backward Navigation to Crumb D1-S2 would produce the Crumb Trail

D1-S1 -> D1-S2 -> D1-S3 -> D1-S2
This is clearly unsatisfactory as this would mean the current State D1-S2 would now display three Crumb links when really it should only show the one Crumb that Navigates back to D1-S1. So backward Navigation to D1-S2 must produce the Crumb Trail

D1-S1 -> D1-S2
Clearly a rule is required to truncate the Trail, but from a Crumb Trail management perspective it is undesirable to treat backward Navigation differently to forward Navigation. Hence, the following directional-agnostic Crumb Trail truncation rule is derived:

Rule 1: The Crumb Trail is truncated whenever a repeated State is encountered
With this rule, since D1-S2 is repeated, the Crumb Trail is truncated back to the first occurrence of D1-S2.

Remember, this rule does not care about the direction of the Navigation. So, if a transition T3 was added from S3 to S2 as shown below

<dialog key="D1" initial="S1" path="~/Default.aspx">
	<state key="S1" page="~/P1.aspx">
		<transition key="T1" to="S2"/>
	</state>
	<state key="S2" page="~/P2.aspx">
		<transition key="T2" to="S3"/>
	</state>
	<state key="S3" page="~/P3.aspx">
		<transition key="T3" to="S2"/>
	</state>
</dialog>
and the user Navigated forward along Transitions T1, T2 and then T3 the resultant Crumb Trail would be truncated and so would again be

D1-S1 -> D1-S2
Also, the Crumb Trail is not preserved when Navigating across different Dialogs since Dialogs represent logical groupings of States and moving from one to another is akin to terminating the current task. Combining this with Rule 1 gives the second rule of Crumb Trail truncation:

Rule 2: The Crumb Trail is started from scratch when a Dialog’s initial State is encountered
To illustrate this rule imagine the user Navigates forward along Transitions T1 and T2 and then jumps to Dialog D2, the Navigation route would be

D1-S1 -> D1-S2 -> D1-S3 -> D2-S1
However, the Crumb Trail would be truncated since S1 is the 'initial' State of D1 and so would become

D2-S1
The PreviousState property on the StateContext class, mentioned in the Navigation section, always tracks the previous State. This might sound similar to the previous Crumb but to show the differences consider some different Navigation routes, taken from the example configuration, and see how these affect the previous Crumb and State as shown in the following table.
Previous Crumb and State Differences
Navigation Route Previous Crumb Previous State
D1-S1 Null Null
D1-S1 -> D1-S2 D1-S1 D1-S1
D1-S1-> D1-S2 -> D1-S3 D1-S2 D1-S2
D1-S1 -> D1-S2 -> D1-S3 -> D1-S2 D1-S1 D1-S3
D1-S1 -> D1-S2 -> D1-S3 -> D1-S1 Null D1-S3
D1-S1 -> D1-S2 -> D2-S1 Null D1-S2
D1-S1 -> D2-S1 -> D1-S1 Null D2-S1
D2-S1 -> D1-S1 -> D1-S2 -> D1-S3 -> D1-S1 Null D1-S3

Sample Web Site

To use Crumb Trail Navigation change the Button Click handler on the Details.aspx Page as shown below. Pressing F5, clicking the Hyperlink and then clicking the Button will return to the Listing State as before.

protected void Button1_Click(object sender, EventArgs e)
{
	StateController.NavigateBack(1);
	//StateController.NavigateBack(1, NavigationMode.Server);
}
Alternatively, change the Button on Details.aspx to a Hyperlink, as shown below

<asp:HyperLink ID="HyperLink1" runat="server">Listing</asp:HyperLink>
Remove the Button Click handler and add the code shown below to the Page_Load method of Details.aspx. The commented line shows a different way to access the same information. Pressing F5 and clicking the Hyperlink on the Details.aspx Page will return to the Listing State.

protected void Page_Load(object sender, EventArgs e)
{
	HyperLink1.NavigateUrl = StateController.GetNavigationBackLink(1);
	//HyperLink1.NavigateUrl = StateController.Crumbs[0].NavigationLink;
}

Last edited Jun 29, 2012 at 11:52 AM by GrahamMendick, version 5