<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>davidpoll.com &#187; Navigation</title>
	<atom:link href="http://www.davidpoll.com/tag/navigation/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.davidpoll.com</link>
	<description>Software development and other goofy geeky goodness.</description>
	<lastBuildDate>Sat, 18 Jun 2011 22:03:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Common Navigation UI and Authorization-driven Sitemaps</title>
		<link>http://www.davidpoll.com/2010/05/10/common-navigation-ui-and-authorization-driven-sitemaps/</link>
		<comments>http://www.davidpoll.com/2010/05/10/common-navigation-ui-and-authorization-driven-sitemaps/#comments</comments>
		<pubDate>Mon, 10 May 2010 22:00:36 +0000</pubDate>
		<dc:creator>david.poll</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Authorization]]></category>
		<category><![CDATA[Controls]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Silverlight 4]]></category>
		<category><![CDATA[Silverlight and Beyond (SLaB)]]></category>
		<category><![CDATA[Sitemap]]></category>
		<category><![CDATA[WCF RIA Services]]></category>

		<guid isPermaLink="false">http://www.davidpoll.com/2010/05/10/common-navigation-ui-and-authorization-driven-sitemaps/</guid>
		<description><![CDATA[Navigation-driven Silverlight applications tend to share some common pieces of UI.&#160; Traditionally, this has required sprinkling HyperlinkButtons throughout the application’s XAML.&#160; For ASP.NET a number of controls intended to drive navigation exist.&#160; These controls are driven by a sitemap, integrate well with authorization and roles (through sitemap trimming), and provide common user experiences around hierarchical [...]]]></description>
			<content:encoded><![CDATA[<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_start --><p>Navigation-driven Silverlight applications tend to share some common pieces of UI.&#160; Traditionally, this has required sprinkling HyperlinkButtons throughout the application’s XAML.&#160; For ASP.NET a <a href="http://msdn.microsoft.com/en-us/library/e468hxky.aspx#SiteNavigationControls" target="_blank">number of controls intended to drive navigation exist</a>.&#160; These controls are driven by a sitemap, integrate well with authorization and roles (through sitemap trimming), and provide common user experiences around hierarchical application structures such as a TreeView-based list of hyperlinks and Breadcrumbs or navigation paths.&#160; These controls provide the user with context as to where in the application/site they currently are as well as where within the application they can go.</p>
<p>In this post, I’ll introduce a few controls that attempt to mimic this behavior in a Navigation-driven Silverlight application.&#160; I have added these controls to <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB" target="_blank">SLaB</a>, and you’re welcome to use and modify them – or use them as examples for your own development – as you see fit.&#160; The controls are:</p>
<ul>
<li>TreeViewNavigator – a control which represents a sitemap as a TreeView </li>
</ul>
<p align="center"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="A TreeView Sitemap." border="0" alt="A TreeView Sitemap." src="http://www.davidpoll.com/wp-content/uploads/2010/05/image.png" width="316" height="516" /> </p>
<ul>
<li>BreadCrumbNavigator – a control which represents your current location within the sitemap’s link hierarchy and allows navigation back up the hierarchy as well as to siblings of any node within the hierarchy </li>
</ul>
<p align="center"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="A BreadCrumb sitemap." border="0" alt="A BreadCrumb sitemap." src="http://www.davidpoll.com/wp-content/uploads/2010/05/image1.png" width="453" height="30" /> </p>
<p>If you’ve been following the evolution of my sample projects, you may have noticed some navigation UI that’s not built into the default navigation application template and has controls that look like the ones I’ve described above.&#160; Surprise, surprise! <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &#160; You can see this in action <a href="http://www.davidpoll.com/Samples/SLaB/" target="_blank">here</a>.</p>
<h3>How does this type of UI work?</h3>
<p>At its core, these controls have the same common set of functionality:</p>
<ul>
<li>Rendering UI based on a sitemap </li>
<li>Keeping UI synchronized with the current page within the application </li>
<li>Trimming the sitemap based upon the roles the current user belongs to and the metadata in the sitemap </li>
</ul>
<p>The goal of these controls is to allow the navigation structure of an application to be exposed to a user in a declarative fashion, much as one can do using <a href="http://msdn.microsoft.com/en-us/library/yy2ykkab.aspx" target="_blank">ASP.NET sitemaps</a>.&#160; The API for the controls above uses Sitemaps that can be specified in XAML, but follow the same general structure as in ASP.NET.</p>
<p>For example, the sitemaps displayed above are produced by the following XAML:</p>
<pre class="code">    <span style="color: blue">&lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">Sitemap </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Key</span><span style="color: blue">=&quot;Sitemap&quot;
                  </span><span style="color: red">Title</span><span style="color: blue">=&quot;DavidPoll.com&quot;
                  </span><span style="color: red">Description</span><span style="color: blue">=&quot;My homepage.  Check it out and see what it's all about!&quot;&gt;
        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot;
                          </span><span style="color: red">Title</span><span style="color: blue">=&quot;Home&quot;
                          </span><span style="color: red">Description</span><span style="color: blue">=&quot;The home page.&quot;
                          </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/Home.xaml&quot; /&gt;
        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;SLaB Features&quot;
                          </span><span style="color: red">Description</span><span style="color: blue">=&quot;Demonstrations of Silverlight and Beyond features.&quot;&gt;
            &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Navigation&quot;&gt;
                &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Local Pages&quot;&gt;
<strong><em>                    &lt;</em></strong></span><strong><em><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span></em></strong><strong><em><span style="color: blue">=&quot;ContentFrame&quot;
                                      </span><span style="color: red">Title</span></em></strong><strong><em><span style="color: blue">=&quot;About&quot;
                                      </span><span style="color: red">Description</span></em></strong><strong><em><span style="color: blue">=&quot;The about page.&quot;
                                      </span><span style="color: red">Roles</span></em></strong><strong><em><span style="color: blue">=&quot;Foo&quot;
                                      </span><span style="color: red">Uri</span></em></strong><span style="color: blue"><strong><em>=&quot;/Views/About.xaml&quot; /&gt;</em></strong>
                    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot;
                                      </span><span style="color: red">Title</span><span style="color: blue">=&quot;A broken link&quot;
                                      </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/NonExistent.xaml&quot; /&gt;
                &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;On-Demand Xaps&quot;
                                  </span><span style="color: red">Description</span><span style="color: blue">=&quot;Pages in Xaps that will be loaded on-demand.&quot;
                                  </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot;
                                  </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/SitemapPage.xaml?sitemapname=OnDemandSitemap&quot;&gt;
                    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;This Domain&quot;&gt;
                        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot;
                                          </span><span style="color: red">Title</span><span style="color: blue">=&quot;Page in a big xap&quot;
                                          </span><span style="color: red">Uri</span><span style="color: blue">=&quot;pack://siteoforigin:,,SecondaryXap.xap/SecondaryXap;component/Page1.xaml&quot; /&gt;
                        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot;
                                          </span><span style="color: red">Title</span><span style="color: blue">=&quot;Awesome Page&quot;
                                          </span><span style="color: red">Uri</span><span style="color: blue">=&quot;pack://siteoforigin:,,TernaryXap.xap/TernaryXap;component/AwesomePage.xaml&quot; /&gt;
                        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot;
                                          </span><span style="color: red">Title</span><span style="color: blue">=&quot;Penguins (mapped Uri + metadata)&quot;
                                          </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/remote/TernaryXap/AwesomePage.xaml?Site=http://www.davidpoll.com&amp;amp;First Name=David&amp;amp;Last Name=Poll&amp;amp;Title=Penguins!&amp;amp;Please rate...&quot; /&gt;
                    &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
                    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Cross-Domain&quot;&gt;
                        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot;
                                          </span><span style="color: red">Title</span><span style="color: blue">=&quot;http://open.depoll.com Page&quot;
                                          </span><span style="color: red">Uri</span><span style="color: blue">=&quot;pack://http:,,open.depoll.com,SimpleApplication,SimpleApplication.xap/SimpleApplication;component/Depoll.xaml?Source=http://open.depoll.com&amp;amp;File=wildlife.wmv&quot; /&gt;
                    &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
                &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Printing&quot;
                                  </span><span style="color: red">Description</span><span style="color: blue">=&quot;Pages that demonstrate printing utilities that simplify pagination of data and printing of complex data sets.&quot;
                                  </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot;
                                  </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/SitemapPage.xaml?sitemapname=PrintingSitemap&quot;&gt;
                    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Collection Printing (DataGrid)&quot;
                                      </span><span style="color: red">Uri</span><span style="color: blue">=&quot;pack://siteoforigin:,,ScratchPrintingProject.xap/ScratchPrintingProject;component/PrintingPage.xaml&quot;
                                      </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; /&gt;
                    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Collection Printing (Template-based)&quot;
                                      </span><span style="color: red">Uri</span><span style="color: blue">=&quot;pack://siteoforigin:,,ScratchPrintingProject.xap/ScratchPrintingProject;component/ItemTemplatePrinting.xaml&quot;
                                      </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; /&gt;
                    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Pre-defined page printing (Template-based)&quot;
                                      </span><span style="color: red">Uri</span><span style="color: blue">=&quot;pack://siteoforigin:,,ScratchPrintingProject.xap/ScratchPrintingProject;component/PredefinedPages.xaml&quot;
                                      </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; /&gt;
                &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Useful XAML Tools&quot;&gt;
                    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot;
                                      </span><span style="color: red">Title</span><span style="color: blue">=&quot;Demo (simple QueryString)&quot;
                                      </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/ObservableDictionaryDemo.xaml?a=b&amp;amp;c=d&amp;amp;e=f&amp;amp;g=h&quot; /&gt;
                    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot;
                                      </span><span style="color: red">Title</span><span style="color: blue">=&quot;Demo (more complex QueryString)&quot;
                                      </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/ObservableDictionaryDemo.xaml?a=b&amp;amp;Name=David Eitan Poll&amp;amp;Url=http://www.davidpoll.com&amp;amp;No Value&amp;amp;Order=Dictionary&quot; /&gt;
                &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
            &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;DavidPoll.com&quot;&gt;
                &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;_blank&quot;
                                  </span><span style="color: red">Title</span><span style="color: blue">=&quot;Home Page&quot;
                                  </span><span style="color: red">Uri</span><span style="color: blue">=&quot;http://www.davidpoll.com&quot; /&gt;
                &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;_blank&quot;
                                  </span><span style="color: red">Title</span><span style="color: blue">=&quot;Navigation Posts&quot;
                                  </span><span style="color: red">Uri</span><span style="color: blue">=&quot;http://www.davidpoll.com/tag/navigation/&quot; /&gt;
                &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;_blank&quot;
                                  </span><span style="color: red">Title</span><span style="color: blue">=&quot;SLaB Posts&quot;
                                  </span><span style="color: red">Uri</span><span style="color: blue">=&quot;http://www.davidpoll.com/tag/silverlight-and-beyond-slab/&quot; /&gt;
                &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;_blank&quot;
                                  </span><span style="color: red">Title</span><span style="color: blue">=&quot;SLaB Download Page&quot;
                                  </span><span style="color: red">Uri</span><span style="color: blue">=&quot;http://www.davidpoll.com/downloads-and-samples/#SLaB&quot; /&gt;
            &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">Sitemap</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>You’ll note that the “About” link in the Sitemap above (bold/italic above) is missing from the TreeView.&#160; This is because the sitemaps do principal-based trimming of the sitemaps, ensuring that users only see the links they’re authorized to see.&#160; </p>
<p>In addition, the controls above stay in sync with the current page the user is viewing.</p>
<p>To get all of this functionality, there are three primary properties to set on the navigation controls (which derive from the Navigator abstract base class for this common functionality):</p>
<ul>
<li>Sitemap – usually, this is set to a Sitemap that is defined in resources somewhere, and may be shared across multiple navigation controls. </li>
<li>CurrentSource – if the navigation control needs to stay in sync with the user’s current location (which is not always the case – e.g. on Error/404-ish pages), bind it to the CurrentSource of the Frame that it will be navigating </li>
<li>Principal – if the navigation control should trim the sitemap based upon the User’s authorization, bind the Principal to be that of the current user.&#160; In the case of RIA Services, this can be done through the WebContext </li>
</ul>
<p>Ultimately, using these controls just requires some simple XAML.&#160; For the TreeViewNavigator:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">TreeViewNavigator </span><span style="color: red">CurrentSource</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">Binding </span><span style="color: red">ElementName</span><span style="color: blue">=ContentFrame, </span><span style="color: red">Path</span><span style="color: blue">=CurrentSource}&quot;
                        </span><span style="color: red">Principal</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">Binding </span><span style="color: red">User</span><span style="color: blue">, </span><span style="color: red">Source</span><span style="color: blue">={</span><span style="color: #a31515">StaticResource </span><span style="color: red">WebContext</span><span style="color: blue">}}&quot;
                        </span><span style="color: red">Sitemap</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">Sitemap</span><span style="color: blue">}&quot; /&gt;
</span></pre>
<p>And for the BreadCrumbNavigator:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">BreadCrumbNavigator </span><span style="color: red">CurrentSource</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">Binding </span><span style="color: red">CurrentSource</span><span style="color: blue">, </span><span style="color: red">ElementName</span><span style="color: blue">=ContentFrame}&quot;
                          </span><span style="color: red">Principal</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">Binding </span><span style="color: red">User</span><span style="color: blue">, </span><span style="color: red">Source</span><span style="color: blue">={</span><span style="color: #a31515">StaticResource </span><span style="color: red">WebContext</span><span style="color: blue">}}&quot;
                          </span><span style="color: red">Sitemap</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">Sitemap</span><span style="color: blue">}&quot; /&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h3>What can I customize?</h3>
<p>These controls are made to work with any ISitemap, which is, at its core, a container for a collection of ISitemapNodes.&#160; You can provide custom implementations of these, customizing your sitemaps to your heart’s content!&#160; For example, you might make sitemaps and sitemap nodes which:</p>
<ul>
<li>Retrieve their data from an ASP.NET xml-based sitemap file </li>
<li>Authorize users for access to nodes based upon more than just roles </li>
<li>Check authorization based on metadata on the page type itself, or by using a NavigationAuthorizer from the AuthContentLoader library </li>
<li>Import one sitemap into another (I’ve actually provided an implementation of this in SLaB so that sitemaps and sub-sitemaps can be used) </li>
</ul>
<p>Furthermore, the controls themselves are look-less, and you should be able to completely re-template them, customizing how hyperlinks are displayed, how much of the tree is expanded, and so on.&#160; If there’s something I’m missing, let me know!</p>
<h3>So, can I see it in action?</h3>
<p>Of course!&#160; You know I never leave you without a demo!&#160; In fact, today I’ve got two for you!</p>
<p>First, the <a href="http://www.davidpoll.com/Samples/SLaB/" target="_blank">SLaB demo application</a> itself uses these controls.&#160; Click around and see how things behave.&#160; You’ll notice the controls are the centerpiece of the navigation UI, but also make appearances throughout the application, <a href="http://www.davidpoll.com/Samples/SLaB/#/Views/SitemapPage.xaml?sitemapname=PrintingSitemap" target="_blank">such as on “category pages”</a> that list only the links within a particular section of the site, and on <a href="http://www.davidpoll.com/Samples/SLaB/#/Views/NonExistent.xaml" target="_blank">error pages</a> within the application, making it easier for users to get back to useful locations within the application.</p>
<p>The second demo application is meant to show role-driven sitemap trimming.&#160; It uses <a href="http://www.silverlight.net/getstarted/riaservices/" target="_blank">WCF RIA Services</a> to drive authentication and authorization, and shows and hides parts of the sitemap based upon the roles the user belongs to.&#160; You can log in using the following credentials:</p>
<p><strong>User</strong>: Test</p>
<p><strong>Password</strong>: _Testing</p>
<p>Experiment with the application and what happens to the navigation controls as you log in and log out.&#160; This also uses the AuthContentLoader from SLaB to perform additional authorization before actually loading any page.</p>
<p><a href="http://www.davidpoll.com/Samples/SitemapBusinessApplication/ScratchBusinessApplicationTestPage.html#/Views/Home.xaml" target="_blank"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Authorization-driven navigation controls" border="0" alt="Authorization-driven navigation controls" src="http://www.davidpoll.com/wp-content/uploads/2010/05/image2.png" width="644" height="432" /></a>&#160;</p>
<p>The XAML for the sitemap in the application above shows how access can be restricted and how trimming takes effect:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">Sitemap </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Key</span><span style="color: blue">=&quot;Sitemap&quot;
                </span><span style="color: red">Title</span><span style="color: blue">=&quot;Scratch Business Application&quot;
                </span><span style="color: red">Description</span><span style="color: blue">=&quot;A sample RIA Services Business application that uses SLaB to represent its navigation and do authorization.&quot;&gt;
    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Home&quot;
                        </span><span style="color: red">Description</span><span style="color: blue">=&quot;The home page for the application&quot;
                        </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/Home.xaml&quot; /&gt;
    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Broken Link&quot;
                        </span><span style="color: red">Description</span><span style="color: blue">=&quot;A broken link&quot;
                        </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/NonExistentPage.xaml&quot; /&gt;
    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Protected Pages (Non-Trimmed)&quot;
                        </span><span style="color: red">Description</span><span style="color: blue">=&quot;Pages protected by authorization&quot;&gt;
        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;About&quot;
                            </span><span style="color: red">Description</span><span style="color: blue">=&quot;The About page for the application&quot;
                            </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/About.xaml&quot; /&gt;
        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Page for registered users&quot;
                            </span><span style="color: red">Description</span><span style="color: blue">=&quot;A page that can only be visited by registered users&quot;
                            </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/RegisteredUsersPage.xaml&quot; /&gt;
    &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Protected Pages (Trimmed)&quot;
                        </span><span style="color: red">Roles</span><span style="color: blue">=&quot;Registered Users&quot;
                        </span><span style="color: red">Description</span><span style="color: blue">=&quot;Pages protected by authorization&quot;&gt;
        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;About&quot;
                            </span><span style="color: red">Description</span><span style="color: blue">=&quot;The About page for the application&quot;
                            </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/About.xaml?trimmed&quot; /&gt;
        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Page for registered users&quot;
                            </span><span style="color: red">Description</span><span style="color: blue">=&quot;A page that can only be visited by registered users&quot;
                            </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/RegisteredUsersPage.xaml?trimmed&quot; /&gt;
    &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Protected Pages (Leaf nodes trimmed)&quot;
                        </span><span style="color: red">Description</span><span style="color: blue">=&quot;Pages protected by authorization&quot;&gt;
        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;About&quot;
                            </span><span style="color: red">Roles</span><span style="color: blue">=&quot;Registered Users&quot;
                            </span><span style="color: red">Description</span><span style="color: blue">=&quot;The About page for the application&quot;
                            </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/About.xaml?leaftrimmed&quot; /&gt;
        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;Page for registered users&quot;
                            </span><span style="color: red">Roles</span><span style="color: blue">=&quot;Registered Users&quot;
                            </span><span style="color: red">Description</span><span style="color: blue">=&quot;A page that can only be visited by registered users&quot;
                            </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/Views/RegisteredUsersPage.xaml?leaftrimmed&quot; /&gt;
    &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">SitemapNode </span><span style="color: red">Title</span><span style="color: blue">=&quot;DavidPoll.com&quot;
                        </span><span style="color: red">Description</span><span style="color: blue">=&quot;David Poll's homepage&quot;
                        </span><span style="color: red">Uri</span><span style="color: blue">=&quot;http://www.davidpoll.com&quot;
                        </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;_blank&quot; /&gt;
&lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">Sitemap</span><span style="color: blue">&gt;
</span></pre>
<h3>Cool… but where are the bits?</h3>
<p>Well, the good news is that you can get all of these controls in my Silverlight and Beyond (SLaB) libraries!&#160; Give them a shot and let me know what you think.&#160; What’s missing from these controls?&#160; What other pieces of user experience are you looking for?&#160; Are the behaviors of the TreeViewNavigator and BreadCrumbNavigator correct for your scenarios and desired UX?</p>
<p>With that said, here’s a summary of the links and access to the source!</p>
<li><a href="http://www.davidpoll.com/Samples/SLaB/">Live Sample</a> (<a href="http://www.davidpoll.com/Download/SLaB/SLaBv0.5.zip">source &#8212; found in the SLaB v0.7 source under &quot;ScratchApplication&quot;</a>) </li>
<li><a href="http://www.davidpoll.com/Samples/SitemapBusinessApplication/ScratchBusinessApplicationTestPage.html" target="_blank">Live Sample using RIA Services for AuthN/AuthX</a> (<a href="http://www.davidpoll.com/Samples/Download/SitemapBusinessApplication.zip" target="_blank">source</a>)&#160;
<p><a href="http://www.davidpoll.com/Download/SLaB/SLaBv0.7.zip">SLaB v0.7</a> (includes source, a sample app, some tests, and binaries) </p>
<ul>
<li>For the latest version, please check out SLaB on my <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB">Downloads and Samples</a> page. </li>
<li>The v0.7 download of SLaB includes the following changes:
<ul>
<li>Added TryImportResourceDictionary that allows XAML resource dictionaries to be imported but fail quietly (so that if not all dependencies for a control are met, other controls in the library (that share the same generic.xaml) can still be used. </li>
<li>Added XamlDependencyAttribute, which ensures that Xaml-only assembly dependencies can be declared and appear as dependencies in the assembly metadata. </li>
<li>Other minor bugfixes </li>
</ul>
</li>
<li>In the interim (since my last post with SLaB), I also produced the v0.6 version, which had the following changes:
<ul>
<li>Made CollectionPrinter work for controls like DataGrid when they auto-generate columns for generic collections (based on the type in IEnumerable&lt;T&gt;) </li>
<li>Added a utility method that allows you to get the MethodInfo for an arbitrary method, including private ones (from anywhere that the method is accessible) </li>
<li>Other minor bugfixes </li>
</ul>
</li>
</ul>
<p>As always, I’d love to know what you think!</p>
</p>
</li>
<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.davidpoll.com/2010/05/10/common-navigation-ui-and-authorization-driven-sitemaps/feed/</wfw:commentRss>
		<slash:comments>39</slash:comments>
		</item>
		<item>
		<title>A &#8220;refreshing&#8221; Authentication/Authorization experience with Silverlight 4</title>
		<link>http://www.davidpoll.com/2010/04/25/a-refreshing-authenticationauthorization-experience-with-silverlight-4/</link>
		<comments>http://www.davidpoll.com/2010/04/25/a-refreshing-authenticationauthorization-experience-with-silverlight-4/#comments</comments>
		<pubDate>Mon, 26 Apr 2010 03:35:28 +0000</pubDate>
		<dc:creator>david.poll</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[ContentLoader]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Silverlight 4]]></category>
		<category><![CDATA[Silverlight and Beyond (SLaB)]]></category>
		<category><![CDATA[WCF RIA Services]]></category>

		<guid isPermaLink="false">http://www.davidpoll.com/2010/04/25/a-refreshing-authenticationauthorization-experience-with-silverlight-4/</guid>
		<description><![CDATA[At the beginning of the year, as part of a series of posts about the INavigationContentLoader extensibility point in Silverlight 4, I described a way to use a content loader to do authorization before allowing a user to navigate to a page.&#160; With the content loader, you can either throw an exception when an unauthorized [...]]]></description>
			<content:encoded><![CDATA[<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_start --><p>At the beginning of the year, as part of a series of posts about the INavigationContentLoader extensibility point in Silverlight 4, <a href="http://www.davidpoll.com/2010/01/01/opening-up-silverlight-4-navigation-authenticationauthorization-in-an-inavigationcontentloader/">I described a way to use a content loader to do authorization before allowing a user to navigate to a page</a>.&#160; With the content loader, you can either throw an exception when an unauthorized user tries to reach a protected Page, redirect your users to another Page, or return a different page (e.g. a Login page) in its stead.&#160; This makes for a fairly nice experience for your users, wherein they are taken directly to a login page (or at least a page with more information about why they cannot access the given page) when they lack the credentials to reach the page they are requesting.</p>
<p>The trouble with this, however, was that once your application reached the login page and your user attempted to log in, there was no clear/easy/universal way to get the user back to the location he/she was originally requesting.&#160; Ideally, an application would keep its context (i.e. the Uri wouldn’t change) when it sends a user to a login page, and take the user to the restricted content once the right credentials are acquired.</p>
<p>When I wrote my original post, I was aware of this limitation, and didn’t have a great solution for it.&#160; Attempting to re-navigate to the requested page was unhelpful because navigating twice to the same Uri is a no-op.&#160; Starting with the Silverlight 4 RC (and continuing into the RTW release, of course), however, such a solution exists!&#160; We quietly added an API to <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.frame(VS.95).aspx">Frame</a> and <a href="http://msdn.microsoft.com/en-us/library/system.windows.navigation.navigationservice(v=VS.95).aspx">NavigationService</a>: <a href="http://msdn.microsoft.com/en-us/library/system.windows.navigation.navigationservice.refresh(v=VS.95).aspx">Refresh()</a>.</p>
<h3>How does refreshing help?</h3>
<p>Calling Frame.Refresh() or NavigationService.Refresh() causes the entire page to be reloaded, meaning that a custom content loader will be called, providing an opportunity to return a different page (or redirect elsewhere).&#160; Without having to make any changes to <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB" target="_blank">SLaB</a> and the <a href="http://www.davidpoll.com/2010/01/01/opening-up-silverlight-4-navigation-authenticationauthorization-in-an-inavigationcontentloader/" target="_blank">AuthContentLoader</a> or <a href="http://www.davidpoll.com/2009/12/07/opening-up-silverlight-4-navigation-event-based-and-error-handling-inavigationcontentloaders/" target="_blank">ErrorPageLoader</a>, we can now produce the desired experience!</p>
<p>Now, our ContentLoader XAML looks like this:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;ContentFrame&quot;
                    </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">ContentFrameStyle</span><span style="color: blue">}&quot;
                    </span><span style="color: red">Source</span><span style="color: blue">=&quot;/Home&quot;&gt;
    &lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.UriMapper</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapper</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapping </span><span style="color: red">Uri</span><span style="color: blue">=&quot;&quot;
                                    </span><span style="color: red">MappedUri</span><span style="color: blue">=&quot;/Views/Home.xaml&quot; /&gt;
            &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapping </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/{pageName}&quot;
                                    </span><span style="color: red">MappedUri</span><span style="color: blue">=&quot;/Views/{pageName}.xaml&quot; /&gt;
        &lt;/</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapper</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.UriMapper</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPage </span><span style="color: red">ExceptionType</span><span style="color: blue">=&quot;UnauthorizedAccessException&quot;
                            </span><span style="color: red">ErrorPageUri</span><span style="color: blue">=&quot;/Views/LoginPage.xaml&quot; /&gt;
            &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPage </span><span style="color: red">ErrorPageUri</span><span style="color: blue">=&quot;/Views/ErrorPage.xaml&quot; /&gt;
            &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader </span><span style="color: red">Principal</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">Binding </span><span style="color: red">User</span><span style="color: blue">, </span><span style="color: red">Source</span><span style="color: blue">={</span><span style="color: #a31515">StaticResource </span><span style="color: red">WebContext</span><span style="color: blue">}}&quot;&gt;
                    &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthorizer</span><span style="color: blue">&gt;
                        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule </span><span style="color: red">UriPattern</span><span style="color: blue">=&quot;^/Views/About\.xaml\??.*$&quot;&gt;
                            &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">Deny </span><span style="color: red">Users</span><span style="color: blue">=&quot;?&quot; /&gt;
                            &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">Allow </span><span style="color: red">Users</span><span style="color: blue">=&quot;*&quot; /&gt;
                        &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule</span><span style="color: blue">&gt;
                        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule </span><span style="color: red">UriPattern</span><span style="color: blue">=&quot;^/Views/RegisteredUsersPage\.xaml\??.*$&quot;&gt;
                            &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">Allow </span><span style="color: red">Roles</span><span style="color: blue">=&quot;Registered Users&quot; /&gt;
                        &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule</span><span style="color: blue">&gt;
                    &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthorizer</span><span style="color: blue">&gt;
                &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader</span><span style="color: blue">&gt;
            &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame</span><span style="color: blue">&gt;
</span></pre>
<p>The primary difference between the XAML above and the original XAML I had posted was to remove the ErrorRedirector (which caused redirection to the login page rather than loading the login page in place of the requested page).&#160; Because this was removed, we no longer need nested ErrorPageLoaders (which existed in order to redirect only in the login case, and load the error page without changing the Uri for other errors).&#160; You’ll note that for the About page and the RegisteredUsers page, access is restricted.&#160; When an UnauthorizedAccessException occurs, users will see the LoginPage.</p>
<p>In the login page, all we need to do now is call NavigationService.Refresh() when the user logs in.&#160; My example uses WCF RIA Service’s WebContext find out this information, but you could just as easily attempt to refresh after a ChildWindow is closed or a Login button is clicked.</p>
<p>My LoginPage code looks like this:</p>
<pre class="code"><span style="color: blue">protected override void </span>OnNavigatedTo(<span style="color: #2b91af">NavigationEventArgs </span>e)
{
    <span style="color: #2b91af">WebContext</span>.Current.Authentication.LoggedIn += Authentication_LoggedIn;
}

<span style="color: blue">protected override void </span>OnNavigatedFrom(<span style="color: #2b91af">NavigationEventArgs </span>e)
{
    <span style="color: #2b91af">WebContext</span>.Current.Authentication.LoggedIn -= Authentication_LoggedIn;
}

<span style="color: blue">void </span>Authentication_LoggedIn(<span style="color: blue">object </span>sender, <span style="color: #2b91af">AuthenticationEventArgs </span>e)
{
    <strong><em><u>NavigationService.Refresh();</u></em></strong>
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Yep, that’s all it takes!&#160; Now, when a user logs in (either by clicking the login button on the page or logging in through some other dialog in the application), the Frame’s content is refreshed, and the AuthContentLoader attempts to verify the user’s credentials once again.</p>
<h3>Cool!&#160; Can I see it in action?</h3>
<p>You know I would never leave you without a sample!&#160; Click the image below to see the sample application (based on my <a href="http://www.davidpoll.com/2010/01/01/opening-up-silverlight-4-navigation-authenticationauthorization-in-an-inavigationcontentloader/">original example</a>, just updated for SL4).&#160; First try navigating to the protected pages without logging in, then try logging in and note how the page automatically is refreshed based upon your new credentials.</p>
<p><strong><em>Login information:</em></strong> Log in with User = “Test”, Password = “_Testing”</p>
<p><a href="http://www.davidpoll.com/Samples/AuthorizingNavigation/ScratchBusinessApplicationTestPage.aspx#/Home" target="_blank"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="A WCF RIA Services application with the AuthContentLoader" border="0" alt="A WCF RIA Services application with the AuthContentLoader" src="http://www.davidpoll.com/wp-content/uploads/2010/04/image5.png" width="644" height="432" /></a></p>
<p>&#160;</p>
<p>You can find the source for this application <a href="http://www.davidpoll.com/Samples/Download/AuthorizingNavigation.zip" target="_blank">here</a>. </p>
<h3>Anything else I should know about Refresh()?</h3>
<p>Without a doubt, Refresh()’s usefulness is not restricted to this scenario.&#160; With custom content loaders, it’s particularly useful to be able to refresh the page, since the page returned as a result of that navigation may change from one attempt to the next.&#160; Even without a custom content loader, Refresh() allows you to create a new instance of a page, making re-initializing the page you’ve navigated to clean and simple.&#160; The behavior is identical to navigating to a new page – the only difference is that the old and new Uris are identical, and the <a href="http://msdn.microsoft.com/en-us/library/system.windows.navigation.navigationmode(VS.95).aspx" target="_blank">NavigationMode</a> of the operation is “Refresh”.</p>
<p>Please note: Refresh() will still respect the <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.page.navigationcachemode(v=VS.95).aspx" target="_blank">NavigationCacheMode</a> of the Page and the <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.frame.cachesize(v=VS.95).aspx" target="_blank">CacheSize</a> of the <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.frame(v=VS.95).aspx" target="_blank">Frame</a>.&#160; If a Page is being cached, calling Refresh() will not create a new instance (but will still cause the Navigating/Navigated events and the corresponding overrides on Page to be raised/called).&#160; To prevent this from happening, set the NavigationCacheMode of the page being refreshed to Disabled before the new page would be loaded (i.e. before Refresh() is called or while handling the Navigating event).</p>
<h3>Is that it?</h3>
<p>Yep, that’s it! <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &#160; Let me know what you think!&#160; What else would you like to see?</p>
<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.davidpoll.com/2010/04/25/a-refreshing-authenticationauthorization-experience-with-silverlight-4/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>On-demand loading of assemblies with Silverlight Navigation &#8211; Revisited for Silverlight 4 Beta</title>
		<link>http://www.davidpoll.com/2010/02/01/on-demand-loading-of-assemblies-with-silverlight-navigation-revisited-for-silverlight-4-beta/</link>
		<comments>http://www.davidpoll.com/2010/02/01/on-demand-loading-of-assemblies-with-silverlight-navigation-revisited-for-silverlight-4-beta/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 08:28:17 +0000</pubDate>
		<dc:creator>david.poll</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[BusyIndicator]]></category>
		<category><![CDATA[ContentLoader]]></category>
		<category><![CDATA[Dynamic Navigation]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Silverlight 4 Beta]]></category>
		<category><![CDATA[Silverlight and Beyond (SLaB)]]></category>

		<guid isPermaLink="false">http://www.davidpoll.com/2010/02/01/on-demand-loading-of-assemblies-with-silverlight-navigation-revisited-for-silverlight-4-beta/</guid>
		<description><![CDATA[Way back in July, shortly after Silverlight 3 was released, I posted a technique that allowed you to use the Navigation framework in the SDK to load pages in dlls that would be downloaded as part of the navigation process.&#160; The solution relied on two things: a workaround to the navigation framework’s inability to navigate [...]]]></description>
			<content:encoded><![CDATA[<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_start --><p>Way back in July, shortly after Silverlight 3 was released, <a href="http://www.davidpoll.com/2009/07/20/on-demand-loading-of-assemblies-with-silverlight-navigation/">I posted a technique</a> that allowed you to use the Navigation framework in the SDK to load pages in dlls that would be downloaded as part of the navigation process.&#160; The solution relied on two things: a workaround to the navigation framework’s inability to navigate to Pages in dynamically-loaded assemblies, and a derived version of the Frame class that hid many methods in order to orchestrate downloads of dlls and their dependencies.</p>
<p>With Silverlight 4’s INavigationContentLoader extensibility point, we can address this scenario much more effectively, and are no longer locked into the workarounds and strict constraints that Silverlight 3’s navigation feature placed on us.&#160; In this post, I’ll walk through the use of another ContentLoader I’ve been working on and look at how it simplifies building multi-xap applications.</p>
<h3></h3>
<h3>Getting a jump-start</h3>
<p>If you’d like to get started quickly and see the magic of multi-xap applications, follow these steps (note: Requires the Silverlight 4 Beta and an active internet connection) or download the source for the steps below <a href="http://www.davidpoll.com/Samples/Download/BasicXapLoaderApp.zip">here</a> (you may need to fix up the references after downloading <a href="http://www.davidpoll.com/Download/SLaB/SLaBv0.3.zip">SLaB</a>):</p>
<ol>
<li>Download and extract <a href="http://www.davidpoll.com/Download/SLaB/SLaBv0.3.zip">SLaB</a> </li>
<li>Open Visual Studio 2010 and create a new Silverlight 4 project using the Silverlight Navigation Application template.&#160; When prompted to create a corresponding ASP.NET web application, just click “OK” and let Visual Studio create a web project for you. </li>
<li>Add a reference to SLaB.Navigation.ContentLoaders.Xap.dll from the extracted Binaries folder. </li>
<li>Add the following line of code to App.xaml.cs: <span style="color: #2b91af">PackUriParser</span>.Initialize(); </li>
<li>Replace the Frame in MainPage.xaml with the following code (new code is bold/italic– the rest is identical to the default project xaml except for formatting): </li>
</ol>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;ContentFrame&quot;
                  </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">ContentFrameStyle</span><span style="color: blue">}&quot;
                  </span><span style="color: red">Source</span><span style="color: blue">=&quot;/Home&quot;
                  </span><span style="color: red">Navigated</span><span style="color: blue">=&quot;ContentFrame_Navigated&quot;
                  </span><span style="color: red">NavigationFailed</span><span style="color: blue">=&quot;ContentFrame_NavigationFailed&quot;&gt;
    &lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.UriMapper</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapper</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapping </span><span style="color: red">Uri</span><span style="color: blue">=&quot;&quot;
                                  </span><span style="color: red">MappedUri</span><span style="color: blue">=&quot;/Views/Home.xaml&quot; /&gt;
            &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapping </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/{pageName}&quot;
                                  </span><span style="color: red">MappedUri</span><span style="color: blue">=&quot;/Views/{pageName}.xaml&quot; /&gt;
        &lt;/</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapper</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.UriMapper</span><span style="color: blue">&gt;
<strong><em>    &lt;</em></strong></span><strong><em><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span></em></strong><strong><em><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">SLaB</span><span style="color: blue">:</span><span style="color: #a31515">XapContentLoader </span><span style="color: red">xmlns</span><span style="color: blue">:</span><span style="color: red">SLaB</span></em></strong><strong><em><span style="color: blue">=&quot;clr-namespace:SLaB.Navigation.ContentLoaders.Xap;assembly=SLaB.Navigation.ContentLoaders.Xap&quot;
                               </span><span style="color: red">EnableCrossDomain</span></em></strong><strong><em><span style="color: blue">=&quot;True&quot; /&gt;
    &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span></em></strong><span style="color: blue"><strong><em>&gt;</em></strong>
&lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<ol start="6">
<li>Run the application. </li>
<li>Replace “#/Home” in your browser’s address bar with “#pack://http:,,open.depoll.com,SimpleApplication,SimpleApplication.xap/SimpleApplication;component/Depoll.xaml?Source=http://open.depoll.com&amp;File=wildlife.wmv” </li>
<li>Wait for a moment, and then enjoy the (admittedly underwhelming) show! </li>
</ol>
<h4>Whoa, what just happened?!</h4>
<p>You just created an application that loaded a page in another xap!&#160; It took only two actions to make this happen: registering the “PackUriParser” and setting the Frame’s ContentLoader to a XapContentLoader with cross-domain access enabled.&#160; When you added the “pack://…” to the browser’s address bar, you told the content loader to downlaod a xap at <a href="http://open.depoll.com/SimpleApplication/SimpleApplication.xap">http://open.depoll.com/SimpleApplication/SimpleApplication.xap</a> (which is on my personal site, and has a very permissive cross-domain policy) and load the page “Depoll.xaml”.</p>
<p>The XapContentLoader makes loading pages in other xaps (and reducing your download sizes) as easy as coming up with a URI that points to the page.&#160; Read on to learn more about how to use the XapContentLoader and some of the problems associated with multi-xap applications.</p>
<h4></h4>
<p><a href="http://11011.net/software/vspaste"></a></p>
<h3>Why load pages in external xaps?</h3>
<p>This has always been a particularly interesting scenario to me.&#160; The size of your application’s xap file can have a big impact on your users’ experience with your Silverlight application.&#160; Since the entire xap and its dependencies (e.g. cached assemblies) must download before users can interact with your application, keeping the xap’s size small means users can start using your application sooner and are less likely to give up and click away.</p>
<p>Partitioning your application into smaller-sized chunks that download only when users attempt to access that piece of functionality can also save bandwidth (since users need not download parts of the application they won’t use).</p>
<p>The folks behind both <a href="http://www.codeplex.com/MEF">MEF</a> (Package catalogs) and <a href="http://www.codeplex.com/CompositeWPF">Prism</a> (Modules) have great libraries that help you accomplish this partitioning.&#160; To me, navigation is a natural delineator of application functionality – Pages represent pieces of functionality your users can access, so triggering loading of other assemblies/xaps as part of navigation means that users will get the pieces of the application when they want to use them.</p>
<p>In this post, I will be outlining a XapContentLoader, which makes loading pages in other Xaps a 2-lines-of-code problem to solve.&#160; I’ve added this ContentLoader and some related utilities to <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB">SLaB</a>, so you can use it yourself or play with the code if you like!</p>
<h3>XapLoader</h3>
<p>The first component I needed to make this scenario work was a way to download and load xap files.&#160; As such, I wrote a XapLoader utility.&#160; The strategy I used for loading xaps was the following:</p>
<ol>
<li>Download the xap </li>
<li>Read the AppManifest.xaml within the xap to locate the assemblies therein </li>
<li>Load all assemblies within the xap </li>
<li>Download zip files for the “ExtensionParts” within the AppManifest (used for the “cached assemblies” feature) </li>
<li>Load the assembly associated with each zip file </li>
</ol>
<p>Why worry about ExtensionParts?&#160; My hope is to use this feature to solve the shared dependency problem.&#160; For example, the System.Windows.Controls.Data.dll file in the SDK (containing the DataGrid control) is a fairly large assembly (446 kb uncompressed).&#160; I’d like to avoid having users download this assembly when the app first loads, so I partition my application into four xaps: Main.xap, Foo.xap, Bar.xap, and Baz.xap.&#160; Foo.xap and Bar.xap both use the DataGrid control.&#160; Since I have no guarantees about the order in which my users will access the application, I need to make sure both of those xaps have access to that assembly, so I partition my application as follows:</p>
<p><a href="http://www.davidpoll.com/wp-content/uploads/2010/02/image.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Multiple xaps have a shared dependency" border="0" alt="Multiple xaps have a shared dependency" src="http://www.davidpoll.com/wp-content/uploads/2010/02/image_thumb.png" width="358" height="293" /></a>This is a bit painful, since now when I download both Foo.xap and Bar.xap, I’m forced to download System.Windows.Controls.Data.dll <strong><em>twice</em></strong>!&#160; Instead, if I turn on the assembly caching feature introduced in Silverlight 3, I can get both Foo.xap and Bar.xap to point to the same System.Windows.Controls.Data.dll.&#160; By taking it out of the actual xaps and making it a separate download, I need only download it once (in fact, the browser’s cache will take care of it for me!).&#160; Now, my application is partitioned in this way:</p>
<p><a href="http://www.davidpoll.com/wp-content/uploads/2010/02/image1.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Xaps with a cached assembly dependency" border="0" alt="Xaps with a cached assembly dependency" src="http://www.davidpoll.com/wp-content/uploads/2010/02/image_thumb1.png" width="640" height="293" /></a></p>
<p>And now I’ve effectively partitioned the application without keeping redundant libraries around that would increase the overall download size of the application.</p>
<p>My implementation allows you to do this (using the same mechanism as “assembly caching”), but has the following limitations:</p>
<ul>
<li>Cached assembly .zip files must contain only one assembly per zip. </li>
<li>The name of the .zip file must be the same as the assembly name (replacing “.dll” with “.zip”) </li>
</ul>
<p>This loader returns a “Xap” object, which has all of the loaded assemblies related with the xap, a “Manifest”, which contains the same data as the Deployment defined in AppManifest.xaml within the xap, and a means to get the original streams from which each assembly was loaded (for use in keeping local copies, if that’s what you’d like to do).&#160; The XapContentLoader, described below, uses this loader to find and load xaps that would contain additional pages.</p>
<h3>XapContentLoader</h3>
<p>The XapContentLoader is an implementation of INavigationContentLoader that will download an external xap and load a page in one of its assemblies.&#160; This content loader uses a slightly modified version of the <a href="http://msdn.microsoft.com/en-us/library/aa970069.aspx">pack uri scheme</a> (which I’m probably abusing a bit here, but oh well <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ).&#160; Technically, it only takes two lines of code/XAML to use the XapContentLoader:</p>
<p>First, add the following line to your Application’s startup code (usually in App.xaml.cs), which registers the pack uri scheme with the built-in Uri class, so that you can create pack Uris in code and XAML without having exceptions be thrown:</p>
<pre class="code"><span style="color: #2b91af">PackUriParser</span>.Initialize();</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Then, in XAML:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;ContentFrame&quot;
                  </span><span style="color: red">Source</span><span style="color: blue">=&quot;/Views/Home.xaml&quot;&gt;
    &lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span><span style="color: blue">&gt;
        <strong><em><span style="text-decoration: underline">&lt;</span></em></strong></span><strong><em><span style="text-decoration: underline"><span style="color: #a31515">xapLoader</span><span style="color: blue">:</span><span style="color: #a31515">XapContentLoader </span></span></em></strong><span style="color: blue"><strong><em><span style="text-decoration: underline">/&gt;</span></em></strong>
    &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>And that’s it!&#160; Alright, that’s all.&#160; See you later…</p>
<p>…</p>
<p>…</p>
<p>…</p>
<p>Ok, ok, I won’t leave you hanging like that!&#160; Let’s look at how you would now use this content loader to load a page in another xap.&#160; First, a quick review of the pack uri scheme as I understand it:</p>
<p><em>pack://&lt;authority&gt;/&lt;path&gt;</em></p>
<p>There are three parts to this Uri:</p>
<ul>
<li>“pack://” – this is the scheme name of the Uri.&#160; All absolute pack Uris begin with this. </li>
<li>“&lt;authority&gt;” – this is actually another Uri (just replace “/” with “,” and escape any other necessary characters).&#160; For the XapContentLoader, this is a path to some xap.&#160; For example, I might use the following authority: “http:,,www.davidpoll.com,xaps,MyApplication.xap”.&#160; This indicates that I’ll be loading a page within the xap at that location.&#160; I also support two other “special” authorities: “application:///” and “siteoforigin://”.&#160; “application:///” cannot have an additional path attached to it, since I translate this as the location of the initial xap from which the application was loaded.&#160; It’s basically equivalent to Application.Current.Host.Source.&#160; “siteoforigin://” is replaced with the directory from which the application’s xap was loaded.&#160; As such, any of the following authorities would be valid:
<ul>
<li>http:,,www.davidpoll.com,xaps,MyApplication.xap </li>
<li>https:,,www.davidpoll.com,securexaps,MySecureApplication.xap </li>
<li>application:,,, </li>
<li>siteoforigin:,,MyApplication.xap (equivalent to the first item in this list if MyApplication.xap was the entry point xap) </li>
</ul>
</li>
<li>“&lt;path&gt;” – this is the path within the xap.&#160; Usually, this looks like: “/SomeLibrary;component/Views/Page1.xaml”.&#160; If no assembly name is provided, I assume they are referring to the “EntryPointAssembly” referred to in the AppManifest.xaml file of the xap. </li>
</ul>
<p>Some examples of valid Uris to navigate to (all equivalent assuming MyApplication.xap was the initial xap):</p>
<ul>
<li>/Views/Page1.xaml </li>
<li>pack://application:,,,/Views/Page1.xaml </li>
<li>pack://application:,,,/MyApplication;component/Views/Page1.xaml </li>
<li>pack://http:,,www.davidpoll.com,xaps,MyApplication.xap/Views/Page1.xaml </li>
<li>pack://http:,,www.davidpoll.com,xaps,MyApplication.xap/MyApplication;component/Views/Page1.xaml </li>
<li>pack://siteoforigin:,,MyApplication.xap/Views/Page1.xaml </li>
<li>pack://siteoforigin:,,MyApplication.xap/MyApplication;component/Views/Page1.xaml </li>
</ul>
<p>Unfortunately, coming up with these Uris can be a bit of a pain, so I’ve provided a custom type of UriMapping that works on a per-xap basis to make this simpler:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.UriMapper</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">navUtils</span><span style="color: blue">:</span><span style="color: #a31515">UriMapper</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">xapLoader</span><span style="color: blue">:</span><span style="color: #a31515">PackUriMapping </span><span style="color: red">XapLocation</span><span style="color: blue">=&quot;siteoforigin://TernaryXap.xap&quot;
                                  </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/remote/{assemblyname}/{path}&quot;
                                  </span><span style="color: red">MappedPath</span><span style="color: blue">=&quot;/{path}&quot; /&gt;
    &lt;/</span><span style="color: #a31515">navUtils</span><span style="color: blue">:</span><span style="color: #a31515">UriMapper</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.UriMapper</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Now, I needn’t ever actually write a pack uri myself.&#160; Instead, I can have hyperlinks like “/remote/TernaryXap/Views/Page1.xaml”, and these mappings will generate the appropriate pack uris for you.&#160; They work just like the UriMapping built into the SDK in terms of replacing values in the MappedPath.&#160; “{assemblyname}” is a special token (that you could omit if you set the PackUriMapping.AssemblyName property) that allows you to make the assembly name part of your path.</p>
<h3>Enhancing the experience</h3>
<p>Great, so now we’ve got navigation integrated with on-demand xap loading.&#160; It takes very few lines of code, and is quick to set up.&#160; Note that my xaps have no concrete knowledge of one another (even the hyperlinks are just text, and users could manually enter other hyperlinks).&#160; But web requests are slow, and could fail.&#160; How can we improve the experience around this type of navigation?</p>
<p>Well, I’ve got two ideas for you that you might recognize: <a href="http://www.davidpoll.com/tag/busyindicator/">BusyIndicator</a> and <a href="http://www.davidpoll.com/2009/12/07/opening-up-silverlight-4-navigation-event-based-and-error-handling-inavigationcontentloaders/">ErrorPageLoader</a>.</p>
<p>Since web requests can fail (lost connectivity, bad links, servers being down, or other random problems), we should make sure users don’t see exceptions under those circumstances.&#160; For this, we’ll whip out the ErrorPageLoader from our trusty utility belt and use it to load a local error page if something goes wrong:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span><span style="color: blue">&gt;
</span><span style="color: blue">        <strong><em><span style="text-decoration: underline">&lt;</span></em></strong></span><strong><em><span style="text-decoration: underline"><span style="color: #a31515">xapLoader</span><span style="color: blue">:</span><span style="color: #a31515">XapContentLoader </span></span></em></strong><span style="color: blue"><strong><em><span style="text-decoration: underline">/&gt;</span></em></strong>
</span><span style="color: blue">    &lt;/</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorContentLoader</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">navigationLoader</span><span style="color: blue">:</span><span style="color: #a31515">PageResourceContentLoader </span><span style="color: blue">/&gt;
    &lt;/</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorContentLoader</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPage </span><span style="color: red">ErrorPageUri</span><span style="color: blue">=&quot;/Views/ErrorPage.xaml&quot; /&gt;
&lt;/</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>You’ll notice that I’ve used the built-in (SDK) PageResourceContentLoader as my ErrorContentLoader.&#160; I did this because, presumably, something bad has happened with the XapContentLoader, so I want to use a ContentLoader with low likelihood of failure in order to display an error page.</p>
<p>Next, users shouldn’t be left hanging while they wait for a link to load.&#160; We can use the BusyIndicator control in the <a href="http://silverlight.codeplex.com">toolkit</a> in order to let the user know that something is going on.&#160; The XapContentLoader has an “IsBusy” property as well as a “Progress” property.&#160; We can make the BusyIndicator’s progress bar display progress and appear by binding it to these properties on the XapContentLoader.&#160; The following handy XAML accomplishes this:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">toolkit</span><span style="color: blue">:</span><span style="color: #a31515">BusyIndicator </span><span style="color: red">IsBusy</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">Binding </span><span style="color: red">ContentLoader</span><span style="color: blue">.ContentLoader.IsBusy, </span><span style="color: red">ElementName</span><span style="color: blue">=ContentFrame}&quot;
                       </span><span style="color: red">DisplayAfter</span><span style="color: blue">=&quot;0:0:0.1&quot;&gt;
    &lt;</span><span style="color: #a31515">toolkit</span><span style="color: blue">:</span><span style="color: #a31515">BusyIndicator.BusyContent</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">Grid</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">Grid.RowDefinitions</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">RowDefinition </span><span style="color: red">Height</span><span style="color: blue">=&quot;Auto&quot; /&gt;
                &lt;</span><span style="color: #a31515">RowDefinition </span><span style="color: red">Height</span><span style="color: blue">=&quot;Auto&quot; /&gt;
            &lt;/</span><span style="color: #a31515">Grid.RowDefinitions</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">TextBlock </span><span style="color: red">Text</span><span style="color: blue">=&quot;Loading page...&quot; </span><span style="color: red">Margin</span><span style="color: blue">=&quot;0,0,0,4&quot; /&gt;
            &lt;</span><span style="color: #a31515">ProgressBar </span><span style="color: red">Grid.Row</span><span style="color: blue">=&quot;1&quot;
                         </span><span style="color: red">Minimum</span><span style="color: blue">=&quot;0&quot;
                         </span><span style="color: red">Maximum</span><span style="color: blue">=&quot;1&quot;
                         </span><span style="color: red">Height</span><span style="color: blue">=&quot;25&quot;
                         </span><span style="color: red">Value</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">Binding </span><span style="color: red">ContentLoader</span><span style="color: blue">.ContentLoader.Progress, </span><span style="color: red">ElementName</span><span style="color: blue">=ContentFrame}&quot; /&gt;
        &lt;/</span><span style="color: #a31515">Grid</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">toolkit</span><span style="color: blue">:</span><span style="color: #a31515">BusyIndicator.BusyContent</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">toolkit</span><span style="color: blue">:</span><span style="color: #a31515">BusyIndicator.ProgressBarStyle</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">Style </span><span style="color: red">TargetType</span><span style="color: blue">=&quot;ProgressBar&quot;&gt;
            &lt;</span><span style="color: #a31515">Setter </span><span style="color: red">Property</span><span style="color: blue">=&quot;Visibility&quot; </span><span style="color: red">Value</span><span style="color: blue">=&quot;Collapsed&quot; /&gt;
        &lt;/</span><span style="color: #a31515">Style</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">toolkit</span><span style="color: blue">:</span><span style="color: #a31515">BusyIndicator.ProgressBarStyle</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;ContentFrame&quot;</span><span style="color: blue">
                      </span><span style="color: red">Source</span><span style="color: blue">=&quot;/Views/Home.xaml&quot;</span><span style="color: blue">&gt;
</span><span style="color: blue">        &lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span><span style="color: blue">&gt;
</span><span style="color: blue">                    &lt;</span><span style="color: #a31515">xapLoader</span><span style="color: blue">:</span><span style="color: #a31515">XapContentLoader</span><span style="color: blue"> /&gt;
</span><span style="color: blue">                &lt;/</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorContentLoader</span><span style="color: blue">&gt;
                    &lt;</span><span style="color: #a31515">navigationLoader</span><span style="color: blue">:</span><span style="color: #a31515">PageResourceContentLoader </span><span style="color: blue">/&gt;
                &lt;/</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorContentLoader</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPage </span><span style="color: red">ErrorPageUri</span><span style="color: blue">=&quot;/Views/ErrorPage.xaml&quot; /&gt;
            &lt;/</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">toolkit</span><span style="color: blue">:</span><span style="color: #a31515">BusyIndicator</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Note that I’ve hidden the BusyIndicator’s default progress bar, and added one to its BusyContent that binds to the XapContentLoader’s progress.&#160; Now, when users navigate to pages and have to wait for them to load, they are presented with the BusyIndicator and a progress bar letting them know how much is left to be downloaded.&#160; The application continues to appear responsive, and users can continue to work with the rest of the application.</p>
<h3>Cross-domain considerations and limiting access</h3>
<p>We’ve now unleashed a lot of power.&#160; Your application can now load pages in <em>any</em> xap that Silverlight can get access to using a WebClient.&#160; If the Frame control you’re using integrates with the browser, users can type any uri into the browser to navigate to, and right now, the XapContentLoader will blindly go and load their code.</p>
<p>This could be a bit of a security issue (I’m no expert, but this one sticks out like a sore thumb).</p>
<p>Suppose domain supersecret.com has a cross-domain policy that allows my domain (and only my domain), davidpoll.com, to access services on it.&#160; My domain is using the XapContentLoader, and can load pages in any xap that WebClient can access.&#160; A developer whose domain is evil.com realizes this, and decides to try to get access to supersecret.com’s services.&#160; He’s able to do this by:</p>
<ul>
<li>Adding a cross-domain policy that allows davidpoll.com to access xaps on evil.com </li>
<li>Pointing the Silverlight application on davidpoll.com to his xap on evil.com (this will work, since WebClient just checks evil.com’s cross-domain policy) </li>
<li>Now that evil.com’s xap has been loaded and is running on davidpoll.com’s application, he can access supersecret.com’s services (since the evil.com’s code is now running on davidpoll.com)! </li>
</ul>
<p>Because of this problem, I’ve disabled cross-domain loading on the XapContentLoader by default.&#160; You can re-enable it, but please be aware of this potential problem.&#160; The <a href="http://www.davidpoll.com/2010/01/01/opening-up-silverlight-4-navigation-authenticationauthorization-in-an-inavigationcontentloader/">AuthContentLoader</a> is a convenient way to restrict access to domains you don’t want users to be able to access just by changing the Uri.&#160; Here, I’ve enabled cross-domain access, but restricted access only to my other domain (this one happens to be my personal website that I don’t update too often <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ):</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader.ContentLoader</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">xapLoader</span><span style="color: blue">:</span><span style="color: #a31515">XapContentLoader </span><span style="color: red"><strong><em><span style="text-decoration: underline">EnableCrossDomain</span></em></strong></span><span style="color: blue"><strong><em><span style="text-decoration: underline">=&quot;True&quot;</span></em></strong> /&gt;
    &lt;/</span><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader.ContentLoader</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthorizer</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule </span><span style="color: red"><strong><em><span style="text-decoration: underline">UriPattern</span></em></strong></span><span style="color: blue"><strong><em><span style="text-decoration: underline">=&quot;pack://((siteoforigin:,,)|(authority:,,)|(http:,,open\.depoll\.com)).*&quot;</span></em></strong>&gt;
            <strong><em><span style="text-decoration: underline">&lt;</span></em></strong></span><strong><em><span style="text-decoration: underline"><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">Allow </span><span style="color: red">Users</span></span></em></strong><span style="color: blue"><strong><em><span style="text-decoration: underline">=&quot;*&quot; /&gt;</span></em></strong>
        &lt;/</span><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule </span><span style="color: red"><strong><em><span style="text-decoration: underline">UriPattern</span></em></strong></span><span style="color: blue"><strong><em><span style="text-decoration: underline">=&quot;pack://.+:,,.*&quot;</span></em></strong>&gt;
            <strong><em><span style="text-decoration: underline">&lt;</span></em></strong></span><strong><em><span style="text-decoration: underline"><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">Deny </span><span style="color: red">Users</span></span></em></strong><span style="color: blue"><strong><em><span style="text-decoration: underline">=&quot;*&quot; /&gt;</span></em></strong>
        &lt;/</span><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthorizer</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">auth</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<p>This allows users to access xaps on my site (open.depoll.com), while denying access to other pack uris.&#160; Coupled with the ErrorContentLoader, a consistent, safe experience can be provided for users.</p>
<h3>MEF and Prism</h3>
<p>At this point, you might be asking yourself why I rolled my own solution to this problem?&#160; MEF and Prism both have very effective implementations for modularization of applications, and you could certainly build very similar ContentLoaders based upon their libraries for loading xaps (in fact, I hope to see folks out there do so! <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ).&#160; Really, the reason I rolled my own libraries for this is twofold:</p>
<ul>
<li>Support for cached assemblies – I wanted to make sure to attempt to solve the shared dependency problem described earlier </li>
<li>Size – it’s important to keep the size of the bootstrapping assemblies small in order to reap the benefits of dynamic loading.&#160; The total size of the libraries required for the XapContentLoader is about 25k compressed.&#160; I’d still like to pare that down, so if folks have ideas, let me know <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </li>
</ul>
<p>If you’ve got ideas for how best to use MEF or Prism with INavigationContentLoader, let me know!&#160; If you’re already using them for modularization and want to integrate them with navigation, this is possible in Silverlight 4 thanks to INavigationContentLoader.</p>
<h3>The goods</h3>
<p>As you know by now if you’ve been following my blog, I never leave you stranded without code and a live sample!&#160; Take a look!</p>
<p><a href="http://www.davidpoll.com/Samples/XapContentLoader/ScratchApplicationTestPage.html" target="_blank"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="An application using XapContentLoader" border="0" alt="An application using XapContentLoader" src="http://www.davidpoll.com/wp-content/uploads/2010/02/image2.png" width="644" height="434" /></a></p>
<p>Click around using the links on top and see what happens to the Uri in the browser’s address bar.&#160; You’ll note the cross-domain access as well as the use of QueryStrings (which still work, of course!).&#160; Open up <a href="http://www.fiddler2.com/Fiddler2/version.asp">Fiddler</a> or some other tool to verify that xaps and zip files for cached assemblies are only downloaded once thanks to browser caching.&#160; Enjoy it!</p>
<p>Finally, some source code for you:</p>
<li><a href="http://www.davidpoll.com/Samples/XapContentLoader/ScratchApplicationTestPage.html">Live Sample</a> (<a href="http://www.davidpoll.com/Download/SLaB/SLaBv0.3.zip">source &#8212; found in the SLaB v0.3 source under &quot;ScratchApplication&quot;</a>) </li>
<li><a href="http://www.davidpoll.com/Download/SLaB/SLaBv0.3.zip">SLaB v0.3</a> (includes source, a sample app, some tests, and binaries)
<ul>
<li>For the latest version, please check out SLaB on my <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB">Downloads and Samples</a> page. </li>
<li>The v0.3 download of SLaB includes the following changes:
<ul>
<li>Added more extensible UriMapper that replicates the built-in UriMapper&#8217;s behavior but allows UriMappings to be more extensible. </li>
<li>Added UiUtilities, the first of which allows you to execute a function on the UI thread and block the calling thread until it has completed (safe to call even from the UI thread) </li>
<li>Added XapLoader, which downloads a Xap and any &quot;cached assemblies&quot; </li>
<li>Added XapContentLoader, which uses the XapLoader to navigate to pages in downloaded assemblies </li>
<li>Added PackUri utilities so that pack Uris can be used to download and navigate to pages in Xaps </li>
<li>Signed all assemblies (public binaries use a private key, another key is distributed with source) </li>
<li>Added a build task that will generate extmap files for all libraries &#8212; now assembly caching works with SLaB assemblies </li>
<li>Fixed a bug with the AuthLoader where all rules would be run, even if one rule already allowed access </li>
<li>Other minor bugfixes </li>
</ul>
</li>
</ul>
<p>Enjoy, and let me know if you have any questions, thoughts, or ideas!</p>
<p><strong><em>Remember</em></strong>, SLaB is just a collection of the samples and experimental components I’ve been putting together so that they’re all in one place.&#160; I can’t make any guarantees about maintaining them, fixing bugs, not making breaking changes, etc., but you’re more than welcome to try them out, use them, and let them inspire your development (or show you what <em>not</em> to do if you really dislike something I’m doing!) <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
</p>
</p>
</li>
<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.davidpoll.com/2010/02/01/on-demand-loading-of-assemblies-with-silverlight-navigation-revisited-for-silverlight-4-beta/feed/</wfw:commentRss>
		<slash:comments>73</slash:comments>
		</item>
		<item>
		<title>Opening up Silverlight 4 Navigation: Authentication/Authorization in an INavigationContentLoader</title>
		<link>http://www.davidpoll.com/2010/01/01/opening-up-silverlight-4-navigation-authenticationauthorization-in-an-inavigationcontentloader/</link>
		<comments>http://www.davidpoll.com/2010/01/01/opening-up-silverlight-4-navigation-authenticationauthorization-in-an-inavigationcontentloader/#comments</comments>
		<pubDate>Fri, 01 Jan 2010 08:01:00 +0000</pubDate>
		<dc:creator>david.poll</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[ContentLoader]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Silverlight 4 Beta]]></category>
		<category><![CDATA[Silverlight and Beyond (SLaB)]]></category>
		<category><![CDATA[WCF RIA Services]]></category>

		<guid isPermaLink="false">http://www.davidpoll.com/2010/01/01/opening-up-silverlight-4-navigation-authenticationauthorization-in-an-inavigationcontentloader/</guid>
		<description><![CDATA[Continuing my series of posts on ways to use INavigationContentLoader (a feature in the Silverlight 4 Beta SDK), in this post, I’ll explore another idea for a composable INavigationContentLoader that protects access to your pages based upon the credentials of the user of your Silverlight application.&#160; To demonstrate its use, I’m using a WCF RIA [...]]]></description>
			<content:encoded><![CDATA[<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_start --><p>Continuing my <a href="http://www.davidpoll.com/tag/contentloader/">series of posts</a> on ways to use INavigationContentLoader (a feature in the Silverlight 4 Beta SDK), in this post, I’ll explore another idea for a composable INavigationContentLoader that protects access to your pages based upon the credentials of the user of your Silverlight application.&#160; To demonstrate its use, I’m using a <a href="http://www.silverlight.net/riaservices">WCF RIA Services</a> application (purely for their Authentication/Authorization provisions).</p>
<p>The basic problem is this: as you would with a website, you build an application with multiple pages – some of which are intended for anonymous users or users in a particular role and some are intended for users with greater privileges.&#160; How do you prevent such users from navigating to those pages and give them an appropriate user experience if they do try to reach pages for which they are not authorized?</p>
<p>To that end, I’ve added another INavigationContentLoader to my <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB">SLaB</a> examples – the “AuthContentLoader” – that checks to see whether your user is authorized to view a page before navigating to it.&#160; If the user is <strong><em>not</em></strong> authenticated, the AuthContentLoader throws, resulting in a NavigationFailed event on the Frame/NavigationService that you can handle in order to provide better feedback to your users if there is an UnauthorizedAccessException.</p>
<h3>Cool – How does it work?</h3>
<p>If you’re familiar with authorization with ASP.NET (settings you might add to your web.config file), this ContentLoader’s use should come pretty easily to you.&#160; For example, in ASP.NET, you might have the following in your web.config:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;
  &lt;</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">allow </span><span style="color: red">roles</span><span style="color: blue">=</span>&quot;<span style="color: blue">Role1, Role2</span>&quot; <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">allow </span><span style="color: red">users</span><span style="color: blue">=</span>&quot;<span style="color: blue">SuperUser</span>&quot;<span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">deny </span><span style="color: red">roles</span><span style="color: blue">=</span>&quot;<span style="color: blue">Role3, Role4</span>&quot; <span style="color: red">users</span><span style="color: blue">=</span>&quot;<font color="#0000ff">LessImpressive</font><span style="color: blue">User</span>&quot; <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">deny </span><span style="color: red">users</span><span style="color: blue">=</span>&quot;<span style="color: blue">?</span>&quot; <span style="color: blue">/&gt;
    &lt;</span><span style="color: #a31515">allow </span><span style="color: red">users</span><span style="color: blue">=</span>&quot;<span style="color: blue">*</span>&quot;<span style="color: blue">/&gt;
  &lt;/</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>I tried to keep the API for the AuthContentLoader quite similar.&#160; With the AuthContentLoader, you can:</p>
<ul>
<li>Allow or deny users access to pages that match a Regular Expression (allowing you to scope the authorization to particular pages) </li>
<li>Allow or deny users access to pages based upon their roles, authentication status, and user name </li>
<li>Wrap any other INavigationContentLoader in order to protect access </li>
</ul>
<p>To accomplish this, there are just a few steps:</p>
<ol>
<li>Set your Frame.ContentLoader to an AuthContentLoader. </li>
<li>Bind AuthContentLoader.Principal to any IPrincipal (in my example, I’ll use the <a href="http://code.msdn.microsoft.com/RiaServices/Release/ProjectReleases.aspx?ReleaseId=2661">built-in authentication context in WCF RIA Services</a>).&#160; This is what the ContentLoader uses to check the user’s credentials. </li>
<li>Add rules for your pages.&#160; If no rule matches a page, the page is assumed to be broadly accessible. </li>
</ol>
<p>Put all of this together, and you end up with something like this:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame ...</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span><span style="color: blue">&gt;
<strong><em>        &lt;</em></strong></span><strong><em><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader </span><span style="color: red">Principal</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">Binding </span><span style="color: red">User</span><span style="color: blue">, </span><span style="color: red">Source</span><span style="color: blue">={</span><span style="color: #a31515">StaticResource </span><span style="color: red">WebContext</span></em></strong><strong><em><span style="color: blue">}}&quot;&gt;
            &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthorizer</span></em></strong><strong><em><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule </span><span style="color: red">UriPattern</span></em></strong><strong><em><span style="color: blue">=&quot;^/Views/About\.xaml\??.*$&quot;&gt;
                    &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">Deny </span><span style="color: red">Users</span></em></strong><strong><em><span style="color: blue">=&quot;?&quot; /&gt;
                    &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">Allow </span><span style="color: red">Users</span></em></strong><strong><em><span style="color: blue">=&quot;*&quot; /&gt;
                &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule</span></em></strong><strong><em><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule </span><span style="color: red">UriPattern</span></em></strong><strong><em><span style="color: blue">=&quot;^/Views/RegisteredUsersPage.xaml\??.*$&quot;&gt;
                    &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">Allow </span><span style="color: red">Roles</span></em></strong><strong><em><span style="color: blue">=&quot;Registered Users&quot; /&gt;
                &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule</span></em></strong><strong><em><span style="color: blue">&gt;
            &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthorizer</span></em></strong><strong><em><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader</span></em></strong><span style="color: blue"><strong><em>&gt;</em></strong>
    &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame</span><span style="color: blue">&gt;
</span></pre>
<p>Here, we have rules for About.xaml (with any querystring) and RegisteredUsersPage.xaml (again, with any querystring).&#160; Note that the UriPattern is a <a href="http://msdn.microsoft.com/en-us/library/hs600312(VS.71).aspx">Regex</a>, and must also take into account the possible query strings that could be attached to the request.&#160; I know it looks a little arcane, but it does the trick, and allows you to specify whole sets of Uri’s that share the same authorization characteristics (e.g. any page in the “PrivateViews” folder could be restricted to Administrators).</p>
<p>The XAML snippet above places restrictions on two pages:</p>
<ul>
<li>About.xaml – anonymous (Principal == null || Principal.Identity == null || Principal.Identity.IsAuthenticated == false) users are denied, and all other users are allowed </li>
<li>RegisteredUsersPage.xaml – only users that belong to the “Registered Users” role are allowed </li>
<li>Users are granted access to all other pages </li>
</ul>
<p>Like the ErrorPageLoader, the AuthContentLoader can take another ContentLoader (but defaults to the PageResourceContentLoader if none is specified), and will delegate the actual loading (after the user has been authorized) to that loader.</p>
<p>And there you go!&#160; Easy as pie!&#160; Feel free to give it a try and play around with it!&#160; Happy New Year!</p>
<h3>Wait!&#160; Don’t stop yet!&#160; Please tie this back to your other posts!</h3>
<p>Relax!&#160; I won’t leave you hanging!&#160; After all, what’s the point of having <strong>two</strong> composable INavigationContentLoaders (AuthContentLoader and <a href="http://www.davidpoll.com/2009/12/07/opening-up-silverlight-4-navigation-event-based-and-error-handling-inavigationcontentloaders/">ErrorPageLoader</a>) if you’re not going to use them together? <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I made a very specific choice with the AuthContentLoader: when the user doesn’t have permission to access a page, the AuthContentLoader throws an exception.&#160; That’s <strong><em>very</em></strong> convenient when you want to use the ErrorPageLoader to handle authentication failures.&#160; The AuthContentLoader, by default, throws an UnauthorizedAccessException, so we can handle that exception explicitly using the ErrorPageLoader.&#160; In this case, we’ll <strong><em>redirect</em></strong> users who visit an unauthorized page to another page that directs them to log in.&#160; The XAML for this follows:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span><span>&gt;
<em><strong>    &lt;errorLoader</strong></em></span><span style="color: blue"><em><strong>:</strong></em></span><em><strong><span>ErrorPageLoader.ErrorPages&gt;
        &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPage </span><span style="color: red"><u>ExceptionType</u></span><span style="color: blue"><u>=&quot;UnauthorizedAccessException&quot;</u> </span></strong></em><em><strong><span><u>ErrorPageUri=&quot;/LoginPage&quot;</u> /&gt;
    &lt;/</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span></strong></em><span><em><strong>ErrorPageLoader.ErrorPages&gt;</strong></em>
<strong><em>    &lt;</em></strong></span><strong><em><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorContentLoader</span></em></strong><strong><em><span style="color: blue">&gt;
        <u>&lt;</u></span><u><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorRedirector </span></u></em></strong><strong><em><span style="color: blue"><u>/&gt;</u>
    &lt;/</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorContentLoader</span></em></strong><span style="color: blue"><strong><em>&gt;</em></strong>
    &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader </span><span style="color: red">Principal</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">Binding </span><span style="color: red">User</span><span style="color: blue">, </span><span style="color: red">Source</span><span style="color: blue">={</span><span style="color: #a31515">StaticResource </span><span style="color: red">WebContext</span><span style="color: blue">}}&quot;&gt;
            &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthorizer</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule </span><span style="color: red">UriPattern</span><span style="color: blue">=&quot;^/Views/About\.xaml\??.*$&quot;&gt;
                    &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">Deny </span><span style="color: red">Users</span><span style="color: blue">=&quot;?&quot; /&gt;
                    &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">Allow </span><span style="color: red">Users</span><span style="color: blue">=&quot;*&quot; /&gt;
                &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule </span><span style="color: red">UriPattern</span><span style="color: blue">=&quot;^/Views/RegisteredUsersPage.xaml\??.*$&quot;&gt;
                    &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">Allow </span><span style="color: red">Roles</span><span style="color: blue">=&quot;Registered Users&quot; /&gt;
                &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule</span><span style="color: blue">&gt;
            &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthorizer</span><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span><span style="color: blue">&gt;
</span></pre>
<p>Cool!&#160; Now, if users navigate to a page they’re not authorized to see, they’ll be redirected to a login page!&#160; Note the exception type being handled (UnauthorizedAccessException), the ErrorPageUri (unmapped, because we’re using the ErrorRedirector, which will cause a brand new navigation to take place – including mapping), and the use of the ErrorRedirector to redirect to a new Uri rather than just loading alternate content (allowing the user to come back to the page rather than assuming that the login page is the real content).</p>
<p>Ok, we’re now in pretty good shape, but users can still hit problems besides the UnauthorizedAccessException, such as attempting to load a page that does not exist.&#160; In my last post, we solved this using an ErrorPageLoader, and we’ll do the same this time.&#160; In these cases, I actually do want to load alternate content rather than redirect to an error page, since this is the typical experience with web error pages (e.g. a 404 page).&#160; I can accomplish this by adding a <strong><em>second</em></strong> ErrorPageLoader to the mix, like so:</p>
<pre class="code"><strong><em><span style="color: blue">&lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span></em></strong><strong><em><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorPages</span></em></strong><strong><em><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPage </span><span style="color: red">ErrorPageUri</span></em></strong><strong><em><span style="color: blue">=&quot;/Views/ErrorPage.xaml&quot; /&gt;
    &lt;/</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorPages</span></em></strong><strong><em><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span></em></strong><span style="color: blue"><strong><em>&gt;</em></strong>
        &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorPages</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPage </span><span style="color: red">ExceptionType</span><span style="color: blue">=&quot;UnauthorizedAccessException&quot; </span><span style="color: red">ErrorPageUri</span><span style="color: blue">=&quot;/LoginPage&quot; /&gt;
            &lt;/</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorPages</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorContentLoader</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorRedirector </span><span style="color: blue">/&gt;
            &lt;/</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ErrorContentLoader</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span><span style="color: blue">&gt;
                &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader </span><span style="color: red">Principal</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">Binding </span><span style="color: red">User</span><span style="color: blue">, </span><span style="color: red">Source</span><span style="color: blue">={</span><span style="color: #a31515">StaticResource </span><span style="color: red">WebContext</span><span style="color: blue">}}&quot;&gt;
                    &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthorizer</span><span style="color: blue">&gt;
                        &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule </span><span style="color: red">UriPattern</span><span style="color: blue">=&quot;^/Views/About\.xaml\??.*$&quot;&gt;
                            &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">Deny </span><span style="color: red">Users</span><span style="color: blue">=&quot;?&quot; /&gt;
                            &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">Allow </span><span style="color: red">Users</span><span style="color: blue">=&quot;*&quot; /&gt;
                        &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule</span><span style="color: blue">&gt;
                        &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule </span><span style="color: red">UriPattern</span><span style="color: blue">=&quot;^/Views/RegisteredUsersPage\.xaml\??.*$&quot;&gt;
                            &lt;</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">Allow </span><span style="color: red">Roles</span><span style="color: blue">=&quot;Registered Users&quot; /&gt;
                        &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthRule</span><span style="color: blue">&gt;
                    &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">NavigationAuthorizer</span><span style="color: blue">&gt;
                &lt;/</span><span style="color: #a31515">authLoader</span><span style="color: blue">:</span><span style="color: #a31515">AuthContentLoader</span><span style="color: blue">&gt;
            &lt;/</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span><span style="color: blue">&gt;
        &lt;/</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span><span style="color: blue">&gt;
    <strong><em>&lt;/</em></strong></span><strong><em><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader.ContentLoader</span></em></strong><strong><em><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">errorLoader</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span></em></strong><span style="color: blue"><strong><em>&gt;</em></strong>
</span></pre>
<p>And that’s it!&#160; Now, when users access your site, they’re protected from any type of error and have access restricted appropriately!&#160; Give it a shot with my <a href="http://www.davidpoll.com/Samples/AuthorizingNavigation/ScratchBusinessApplicationTestPage.aspx#/Home">live sample application</a>:</p>
<p><strong><em>Note:</em></strong> Log in with User = “Test”, Password = “_Testing”</p>
<p><strong><em>Also Note:</em></strong> I’ve been having a little trouble with my server, so if this doesn’t work for you, feel free to try downloading and running the code locally (see below for a link).</p>
<p><a href="http://www.davidpoll.com/Samples/AuthorizingNavigation/ScratchBusinessApplicationTestPage.aspx#/Home"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Live Sample Application" border="0" alt="Live Sample Application" src="http://www.davidpoll.com/wp-content/uploads/2009/12/image2.png" width="637" height="484" /></a></p>
<p>First, try clicking on the restricted links at the top of the application and observe the login page that appears.&#160; Next, click the broken link (or type something random into your browser after the “#” in the URL), and observe the error page that appears.&#160; Now, log in to the application (feel free to create your own account or use the test account above – any account should give you access to the pages that are currently restricted), and try visiting those pages again!</p>
<h3></h3>
<h3>Ok, I think I’m beginning to get it.&#160; Give me the goods so I can go play with it!</h3>
<p>As always, I can’t leave you empty-handed.&#160; I’ve added the AuthContentLoader to SLaB, which you can download to get both binaries and code.&#160; I’ve also included the source (which requires <a href="http://www.silverlight.net/riaservices">WCF RIA Services</a> and the Silverlight 4 Beta) for the demo application I linked to above:</p>
<ul>
<li><a href="http://www.davidpoll.com/Samples/AuthorizingNavigation/ScratchBusinessApplicationTestPage.aspx#/Home">Live Sample</a> (<a href="http://www.davidpoll.com/Samples/Download/AuthorizingNavigation.zip">source</a>) </li>
<li><a href="http://www.davidpoll.com/Download/SLaB/SLaBv0.0.2.zip">SLaB v0.0.2</a> (includes source, a sample app, some tests, and binaries)
<ul>
<li>For the latest version, please check out SLaB on my <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB">Downloads and Samples</a> page. </li>
<li>The v0.0.2 download of SLaB includes:
<ul>
<li>AuthContentLoader and related classes </li>
<li>ErrorPageLoader moved into its own assembly (to keep its size down) </li>
</ul>
</li>
</ul>
</li>
</ul>
<h3></h3>
<h3>In Conclusion&#8230;</h3>
<p>In my humble opinion, there is a lot of power in composing these types of INavigationContentLoaders.&#160; With the AuthContentLoader, you can prevent Uri’s from being loaded in the context of your application.&#160; Whether you’re just trying to provide a good user experience or actually prevent users from reaching certain Uri’s (e.g. dynamically downloaded XAPs/assemblies that should only be accessible if you’re logged in) a ContentLoader like this could be useful.&#160; The AuthContentLoader works well with WCF RIA Services, which provides easy access through its “WebContext” concept to a User that represents both an IPrinciple and an IIdentity.&#160; Stay tuned for more ideas – I’m still working on some fun little experiments.&#160; Hopefully these posts inspire some cool ideas!&#160; If you’ve got ‘em, I’d love to hear ‘em!</p>
<p><strong>Remember</strong>, SLaB is just a collection of the samples and experimental components I’ve been putting together so that they’re all in one place.&#160; I can’t make any guarantees about maintaining them, fixing bugs, not making breaking changes, etc., but you’re more than welcome to try them out, use them, and let them inspire your development (or show you what <em>not</em> to do if you really dislike something I’m doing!) <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<h3></h3>
<h3>Disclaimer</h3>
<p>The AuthContentLoader <strong><em>does not</em></strong> protect your data in any way – it simply provides a user experience around navigating to pages that may have restricted access.&#160; Users can still open up your XAP and see its contents (so the XAML/code for those restricted pages isn’t protected), but it does do an effective job of limiting what users are able to access within your application.&#160; You should still be aggressively securing your application if need be.&#160; <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Don’t you have something else to say?</h3>
<p>Oh, yeah!&#160; Happy New Year!&#160; Here’s to (and good riddance to) the noughties, bring on the teens!&#160; I hope you all have had a wonderful holiday season, and enjoy prosperity in the year ahead.</p>
<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.davidpoll.com/2010/01/01/opening-up-silverlight-4-navigation-authenticationauthorization-in-an-inavigationcontentloader/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>Opening up Silverlight 4 Navigation: Event-based and Error-Handling INavigationContentLoaders</title>
		<link>http://www.davidpoll.com/2009/12/07/opening-up-silverlight-4-navigation-event-based-and-error-handling-inavigationcontentloaders/</link>
		<comments>http://www.davidpoll.com/2009/12/07/opening-up-silverlight-4-navigation-event-based-and-error-handling-inavigationcontentloaders/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 08:01:00 +0000</pubDate>
		<dc:creator>david.poll</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[ContentLoader]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Silverlight 4 Beta]]></category>
		<category><![CDATA[Silverlight and Beyond (SLaB)]]></category>

		<guid isPermaLink="false">http://www.davidpoll.com/2009/12/07/opening-up-silverlight-4-navigation-event-based-and-error-handling-inavigationcontentloaders/</guid>
		<description><![CDATA[Last week, I gave an introduction to INavigationContentLoader, a Silverlight 4 Beta SDK extensibility point that allows you to load arbitrary content in conjunction with the Silverlight navigation feature, and walked you through building a Typename-based content loader.&#160; That’s all well and good, but it’s an awful lot of work to go to in order [...]]]></description>
			<content:encoded><![CDATA[<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_start --><p>Last week, I gave an introduction to INavigationContentLoader, a Silverlight 4 Beta SDK extensibility point that allows you to load arbitrary content in conjunction with the Silverlight navigation feature, and walked you through building a <a href="http://www.davidpoll.com/2009/11/30/opening-up-silverlight-4-navigation-introduction-to-inavigationcontentloader/" target="_blank">Typename-based content loader</a>.&#160; That’s all well and good, but it’s an awful lot of work to go to in order to build a simple INavigationContentLoader (following the async pattern, fully implementing the interface, etc.).&#160; Sometimes, all you really want to do is handle a few events in order to be up and running, fully integrated with Silverlight navigation.&#160; Furthermore, because of the nature of the feature, Navigation has a high potential for error conditions.&#160; For example, what happens if a user tries to follow a broken link or types a bad address into the browser’s address bar (with a browser-integrated frame)?&#160; How do you gracefully let your users know that something went wrong and give them some options about what to do next?</p>
<p>In this post, I’ll use the INavigationContentLoader extensibility point in the Silverlight 4 Beta SDK to address these two issues.&#160; For convenience, starting with this post, I’ll be compiling my helper classes and utilities into a set of libraries I’ll call <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB" target="_blank">“Silverlight and Beyond” (SLaB)</a>, which you’re more than welcome to <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB" target="_blank">download</a> and use (although I make no guarantees about its functionality or that I won’t introduce breaking changes as I make additions).</p>
<h3>An Event-Based INavigationContentLoader</h3>
<p>For simple custom content loading like we did with the <a href="http://www.davidpoll.com/2009/11/30/opening-up-silverlight-4-navigation-introduction-to-inavigationcontentloader/">Typename-based content loader</a>, writing a full implementation of an INavigationContentLoader can really be overkill.&#160; For quick-and-dirty navigation scenarios, it would be much easier to just use a generic INavigationContentLoader and handle some events in order to perform a load operation.&#160; In the simplest case, loading is just a synchronous operation that creates an instance of a page based on your logic (a simple switch statement might be appropriate, and this gives you an opportunity to provide constructor parameters or do other initialization on your pages).</p>
<p>With that in mind, I threw together a SynchronousEventContentLoader that simplifies these cases.&#160; Now, you we can rewrite the <a href="http://www.davidpoll.com/2009/11/30/opening-up-silverlight-4-navigation-introduction-to-inavigationcontentloader/">Typename-based content loader</a> as follows:</p>
<p>In MainPage.xaml:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;ContentFrame&quot;</span><span style="color: blue">
              </span><span style="color: red">Source</span><span style="color: blue">=&quot;/TypenameEventContentLoader.Views.Home&quot;&gt;</span><span style="color: blue">
    &lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span><span style="color: blue">&gt;
        <strong><em><u>&lt;</u></em></strong></span><strong><em><u><span style="color: #a31515">loader</span><span style="color: blue">:</span><span style="color: #a31515">SynchronousEventContentLoader </span><span style="color: red">Load</span></u></em></strong><span style="color: blue"><strong><em><u>=&quot;SynchronousEventContentLoader_Load&quot;
</u></em></strong>                                              </span><span style="color: red"><strong><em><u>CanLoad</u></em></strong></span><span style="color: blue"><strong><em><u>=&quot;SynchronousEventContentLoader_CanLoad&quot; /&gt;
</u></em></strong>    &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame</span><span style="color: blue">&gt;
</span></pre>
<p>In MainPage.xaml.cs, we handle the Load/CanLoad events as follows (virtually identical to our <a href="http://www.davidpoll.com/2009/11/30/opening-up-silverlight-4-navigation-introduction-to-inavigationcontentloader/">previous impelementation</a>):</p>
<pre class="code"><span style="color: blue">private </span><span style="color: #2b91af">LoadResult </span>SynchronousEventContentLoader_Load(<span style="color: #2b91af">Uri </span>targetUri, <span style="color: #2b91af">Uri </span>currentUri)
{
    <span style="color: #2b91af">Type </span>t = <span style="color: #2b91af">Type</span>.GetType(GetTypeNameFromUri(targetUri), <span style="color: blue">false</span>, <span style="color: blue">true</span>);
    <span style="color: blue">object </span>instance = <span style="color: #2b91af">Activator</span>.CreateInstance(t);
    <span style="color: blue">var </span>result = <span style="color: blue">new </span><span style="color: #2b91af">LoadResult</span>(instance);
    <span style="color: blue">return </span>result;
}

<span style="color: blue">private bool </span>SynchronousEventContentLoader_CanLoad(<span style="color: #2b91af">Uri </span>targetUri, <span style="color: #2b91af">Uri </span>currentUri)
{
    <span style="color: blue">string </span>typeName = GetTypeNameFromUri(targetUri);
    <span style="color: #2b91af">Type </span>t = <span style="color: #2b91af">Type</span>.GetType(typeName, <span style="color: blue">false</span>, <span style="color: blue">true</span>);
    <span style="color: blue">if </span>(t == <span style="color: blue">null</span>)
        <span style="color: blue">return false</span>;
    <span style="color: blue">var </span>defaultConstructor = t.GetConstructor(<span style="color: blue">new </span><span style="color: #2b91af">Type</span>[<span style="color: brown">0</span>]);
    <span style="color: blue">if </span>(defaultConstructor == <span style="color: blue">null</span>)
        <span style="color: blue">return false</span>;
    <span style="color: blue">return true</span>;
}

<span style="color: blue">private string </span>GetTypeNameFromUri(<span style="color: #2b91af">Uri </span>uri)
{
    <span style="color: blue">if </span>(!uri.IsAbsoluteUri)
        uri = <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">&quot;dummy:///&quot;</span>, <span style="color: #2b91af">UriKind</span>.Absolute), uri.OriginalString);
    <span style="color: blue">return </span><span style="color: #2b91af">Uri</span>.UnescapeDataString(uri.AbsolutePath.Substring(<span style="color: brown">1</span>));
}</pre>
<p>And that’s it!&#160; If you just want a quick switch statement so that you can add initialization (constructor parameters, etc.) to your pages, this is a nice, easy way to go.&#160; If there’s a need for something similar that supports asynchronous operations, making a similar INavigationContentLoader for that is fairly straightforward.</p>
<h3></h3>
<h3>Handling Errors using an INavigationContentLoader</h3>
<p>There’s a large variety of errors that can occur during navigation – the Uri may not resolve to anything real, the Page may throw an exception while being constructed, your user doesn’t have permission to see a particular page, or your particular INavigationContentLoader may hit an exceptional condition (no network access, invalid syntax when parsing a config file, etc.).&#160; In order to develop a robust application, we need to be able to handle these error conditions gracefully.&#160; For those of you familiar with web development, this is not too dissimilar from writing error pages to handle 404 (page not found) conditions, etc.</p>
<p>One way to handle error conditions with the Navigation framework is to handle the NavigationFailed event on the Frame or NavigationService, but this means that when navigation does fail, your only options are to navigate to a new page altogether (resulting in extra history entries and the potential for further failures) or to show some other UI, which may leave your users with a blank page in front of them (in the Frame) if they navigate to the page directly (rather than from a link in your application).&#160; Our approach will be to load a different page altogether when loading content fails.&#160; For this, I’ve created an ErrorPageLoader, another INavigationContentLoader.</p>
<p>Of additional importance is that this content loader doesn’t really own the content loading process from end to end.&#160; In order for the ErrorPageLoader to be generalized, it must be composable, allowing it to delegate loading to another INavigationContentLoader except during error conditions.&#160; In this case, the ErrorPageLoader has two INavigationContentLoaders that it may delegate its work to:</p>
<ul>
<li><strong>ErrorPageLoader.ContentLoader</strong>, which is what the ErrorPageLoader will attempt to use in order to service standard load requests.&#160; <em>This defaults to the PageResourceContentLoader built into Silverlight 4, which is what the Frame/NavigationService use by default.</em> </li>
<li><strong>ErrorPageLoader.ErrorContentLoader</strong>, which is what the ErrorPageLoader will use to load pages in case the ErrorPageLoader.ContentLoader fails.&#160; <em>If this value is null, the ErrorPageLoader uses ErrorPageLoader.ContentLoader to load the error pages.</em> </li>
</ul>
<p>This dichotomy allows you to delegate to a more reliable INavigationContentLoader (e.g. the PageResourceContentLoader) should your primary one fail.&#160; For example, if I use an INavigationContentLoader that downloads external assemblies on the fly, and the downlaod fails, error pages should be loaded locally rather than trying to load from a remote location.</p>
<p>Next, we need a way to specify what Uri to load as an error page based on the type of error that occurred.&#160; The ErrorPageLoader has an <strong>ErrorPages</strong> property that takes a set of IErrorPages – an interface that maps an exception type to a Uri.&#160; I’ve provided a default implementation for use in XAML that takes a name of an Exception type to handle (or none at all, in which case it becomes a catch-all handler) and a Uri (unmapped) to load using the ErrorContentLoader when those error conditions arise.</p>
<p>With these things in mind, the usage of the ErrorPageLoader looks like this:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;ContentFrame&quot;</span><span style="color: blue">
                  </span><span style="color: red">Source</span><span style="color: blue">=&quot;/Home&quot;</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.UriMapper</span><span style="color: blue">&gt;
      &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapper</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapping </span><span style="color: red">Uri</span><span style="color: blue">=&quot;&quot; </span><span style="color: red">MappedUri</span><span style="color: blue">=&quot;/Views/Home.xaml&quot;/&gt;
        &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapping </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/{pageName}&quot; </span><span style="color: red">MappedUri</span><span style="color: blue">=&quot;/Views/{pageName}.xaml&quot;/&gt;
      &lt;/</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapper</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.UriMapper</span><span style="color: blue">&gt;
<strong><em>    &lt;</em></strong></span><strong><em><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span></em></strong><strong><em><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span></em></strong><strong><em><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPage </span><span style="color: red">ExceptionType</span></em></strong><strong><em><span style="color: blue">=&quot;System.InvalidOperationException&quot;
                               </span><span style="color: red">ErrorPageUri</span></em></strong><strong><em><span style="color: blue">=&quot;/Views/InvalidOperationErrorPage.xaml&quot; /&gt;
            &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPage </span><span style="color: red">ExceptionType</span></em></strong><strong><em><span style="color: blue">=&quot;System.InvalidCastException&quot;
                               </span><span style="color: red">ErrorPageUri</span></em></strong><strong><em><span style="color: blue">=&quot;/Views/InvalidCastErrorPage.xaml&quot; /&gt;
            &lt;</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPage </span><span style="color: red">ErrorPageUri</span></em></strong><strong><em><span style="color: blue">=&quot;/Views/DefaultErrorPage.xaml&quot; /&gt;
        &lt;/</span><span style="color: #a31515">loaders</span><span style="color: blue">:</span><span style="color: #a31515">ErrorPageLoader</span></em></strong><strong><em><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span></em></strong><span style="color: blue"><strong><em>&gt;</em></strong>
&lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame</span><span style="color: blue">&gt;
</span></pre>
<p>There are just a few things to note here:</p>
<ul>
<li>Because I didn’t specify an ErrorPageLoader.ContentLoader in the example above, the PageResourceContentLoader will be used to load pages normally. </li>
<li>The ExceptionType isn’t actually of type Type, since Silverlight XAML doesn’t support custom properties of type Type at the moment. </li>
<li>The ErrorPageUri is an unmapped Uri (i.e. it does not follow the UriMapper-based scheme) </li>
<li>When an error page is loaded, the CurrentSource of the Frame/NavigationService (or the browser if the Frame is browser-integrated) remains the same.&#160; If you want the Uri to change, use the <strong>ErrorRedirector</strong> INavigationContentLoader that I’ve provided to redirect to the error Uri. </li>
</ul>
<p>The final step in the process of error handling is to provide some good feedback to your users about what went wrong.&#160; In order to do this, it’s useful to know what exception occurred that caused the error page to be loaded.&#160; As such, the ErrorPageLoader has an attached “Error” property, which it attaches to any page loaded using the ErrorContentLoader.&#160; This attached property holds the exception that was thrown during loading.</p>
<p>I threw together a little example of an error page that uses this attached property, like so (alternatively, I could have bound to it in XAML):</p>
<pre class="code"><span style="color: blue">protected override void </span>OnNavigatedTo(<span style="color: #2b91af">NavigationEventArgs </span>e)
{
    <span style="color: blue">this</span>.errorInformation.Content = <span style="color: #2b91af">ErrorPageLoader</span>.GetError(<span style="color: blue">this</span>);
    <span style="color: blue">this</span>.uriLink.NavigateUri = e.Uri;
}</pre>
<p>You can see an example of the ErrorPageLoader in action here:</p>
<p><a href="http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="Live ErrorPageLoader sample" border="0" alt="Live ErrorPageLoader sample" src="http://www.davidpoll.com/Images/OpeningupSilverlight4NavigationEventbase_102F3/image.png" width="644" height="435" /></a></p>
<p>And here are some things to try:</p>
<ul>
<li>A good link: <a title="http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html#/Home" href="http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html#/Home">http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html#/Home</a> </li>
<li>A broken link: <a title="http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html#/NonExistent" href="http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html#/NonExistent">http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html#/NonExistent</a> </li>
<li>A link to a page that throws an exception when it’s being constructed: <a title="http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html#/BrokenPage" href="http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html#/BrokenPage">http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html#/BrokenPage</a> </li>
</ul>
<p>Notice what happens to the Uri (everything after the “#” in the URL) when navigating to pages that are in error.&#160; Try changing the URI to anything you can think of – you’ll always be able to navigate there, but the links will just lead you to error pages.</p>
<p>If you’re really brave, here are some other experiments to consider:</p>
<ul>
<li>Wrap the ErrorPageLoader around the Typename-based content loader from my previous post, and try navigating to Types without a default constructor or that don’t exist </li>
<li>Wrap the ErrorPageLoader around your own INavigationContentLoader (or the SynchronousEventContentLoader).&#160; When do you expect loading to fail?&#160; What should the user experience be when something does go wrong?&#160; (here’s an idea: throw an exception if the user isn’t logged in, and use the ErrorPageLoader to show a login page) </li>
</ul>
<h4></h4>
<h3>So… How does it work?</h3>
<p>Well, the behavior of the ErrorPageLoader is pretty straightforward:</p>
<ul>
<li>Try to load the page from the targetUri using the ErrorPageLoader.ContentLoader </li>
<li>If an exception is thrown during that INavigationContentLoader’s BeginLoad or EndLoad, or if the loader returns something invalid (e.g. the LoadResult contains something that’s not a Page or a UserControl)…
<ul>
<li>Find the first IErrorPage in ErrorPageLoader.ErrorPages </li>
<li>If an IErrorPage was found, try to load the Uri that the IErrorPage maps to using ErrorPageLoader.ErrorContentLoader
<ul>
<li>If the LoadResult has a Page rather than a redirect, attach the Exception using the Error attached property </li>
</ul>
</li>
<li>Otherwise, throw the exception during EndLoad() (i.e. allow the exception to fall through) </li>
</ul>
</li>
<li>Return the LoadResult </li>
</ul>
<p>And really, that’s the nature of a composable INavigationContentLoader: add some functionality around an existing INavigationContentLoader, and pass the remaining results on through to the Frame/NavigationService.&#160; Such content loaders make it easy to decorate existing loaders with functionality that applies to your application.&#160; I’ve got a few ideas for these, but I’d love to hear what you think!&#160; Here are a few that I have on my mind:</p>
<ul>
<li>Error pages (in case you didn’t just finish reading about those <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ) </li>
<li>Authenticating/Authorizing (redirect me to a login page or an error page if I’m not authorized to see the one I requested) </li>
<li>QueryString initialization (reflect over properties on the page to set based upon the query string of the Uri) </li>
<li>Chainer (if the first INavigationContentLoader in my list didn’t work, try the next one!) </li>
</ul>
<p>With that said, <em><u>what else would you like to see?</u></em>&#160; If something particularly compelling arises, I’d be happy to add it to my “<a href="http://www.davidpoll.com/downloads-and-samples/#SLaB">Silverlight and Beyond (SLaB)</a>” library!</p>
<h3>And, as always, the goods…</h3>
<p>You didn’t really think I’d leave you without some code and samples, did you?</p>
<ul>
<li><a href="http://www.davidpoll.com/Samples/ErrorContentLoaderSample/TestPage.html">Live sample</a> </li>
<li><a href="http://www.davidpoll.com/Download/SLaB/SLaBv0.0.1.zip">SLaB v0.0.1</a> (includes source, a sample app, some tests, and binaries)
<ul>
<li>For the latest version, please check out SLaB on my <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB">Downloads and Samples</a> page. </li>
<li>The v0.0.1 download of SLaB includes:
<ul>
<li>ErrorPageLoader and related classes </li>
<li>SynchronousEventContentLoader </li>
</ul>
</li>
</ul>
</li>
</ul>
<h3>P.S.&#160; What on Earth is <a href="http://www.davidpoll.com/downloads-and-samples/#SLaB">SLaB</a>?</h3>
<p>I mentioned it briefly at the beginning of this post, but my plan is to start putting all of my utility classes, tools, controls, and so forth in one easily-downloadable and easy-to-use package.&#160; For now, I’m calling this SLaB, or “Silverlight and Beyond” (just because I’m into really corny acronyms).&#160; Hopefully you’ll find it useful either as an example of what to do (or if you really dislike me – what <strong><em><u>not</u></em></strong> to do <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ), or to use within your own applications.&#160; If you’re curious about how or why I did something, or if you find a bug, let me know!&#160; Who knows?&#160; Maybe you’ll inspire another blog post!</p>
<p>Just one note: it’s just little ol’ me working on SLaB, and I make no guarantees of correct behavior, frequent updates, lack of breaking changes, full documentation, support, or anything of the sort.&#160; Nonetheless, I look forward to adding to it whenever my curiosity is piqued enough to make something useful or demonstrative, and I hope you find it useful too!</p>
<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.davidpoll.com/2009/12/07/opening-up-silverlight-4-navigation-event-based-and-error-handling-inavigationcontentloaders/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Opening up Silverlight 4 Navigation: Introduction to INavigationContentLoader</title>
		<link>http://www.davidpoll.com/2009/11/30/opening-up-silverlight-4-navigation-introduction-to-inavigationcontentloader/</link>
		<comments>http://www.davidpoll.com/2009/11/30/opening-up-silverlight-4-navigation-introduction-to-inavigationcontentloader/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 19:37:18 +0000</pubDate>
		<dc:creator>david.poll</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[ContentLoader]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Silverlight 4 Beta]]></category>

		<guid isPermaLink="false">http://www.davidpoll.com/?p=195</guid>
		<description><![CDATA[Quick links to followup posts: Event-based and Error-Handling INavigationContentLoaders Authentication/Authorization in an INavigationContentLoader On-demand loading of assemblies with Silverlight Navigation – Revisited for Silverlight 4 Beta If you haven’t noticed by now (or been following my previous blog posts), I happen to really enjoy exploring the Navigation feature in Silverlight.&#160; A while back, I posted [...]]]></description>
			<content:encoded><![CDATA[<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_start --><p><strong><em>Quick links to followup posts:</em></strong></p>
<ul>
<li><a href="http://www.davidpoll.com/2009/12/07/opening-up-silverlight-4-navigation-event-based-and-error-handling-inavigationcontentloaders/"><em>Event-based and Error-Handling INavigationContentLoaders</em></a></li>
<li><a href="http://www.davidpoll.com/2010/01/01/opening-up-silverlight-4-navigation-authenticationauthorization-in-an-inavigationcontentloader/"><em>Authentication/Authorization in an INavigationContentLoader</em></a></li>
<li><a href="http://www.davidpoll.com/2010/02/01/on-demand-loading-of-assemblies-with-silverlight-navigation-revisited-for-silverlight-4-beta/"><em>On-demand loading of assemblies with Silverlight Navigation – Revisited for Silverlight 4 Beta</em></a></li>
</ul>
<p>If you haven’t noticed by now (or been following my previous blog posts), I happen to really enjoy exploring the Navigation feature in Silverlight.&#160; A while back, I <a href="http://www.davidpoll.com/tag/navigation" target="_blank">posted a number of workarounds and tips</a> for some desirable scenarios using the Navigation feature in Silverlight 3.&#160; Then… I went silent.&#160; And the reason: I’ve been waiting for an extensibility point to be opened up in Silverlight navigation.&#160; In the <a href="http://www.silverlight.net/getstarted/silverlight-4-beta/" target="_blank">Silverlight 4 beta</a>, that extensibility point has arrived as the INavigationContentLoader.</p>
<p>The ContentLoader extensibility point allows developers to handle the page loading process themselves, much as you would with a GenericHandler in ASP.NET.&#160; You’re given some context on what to load (in this case a target Uri), then it’s up to you as the developer to decide how to load it.&#160; Your handling of these requests can be as specialized or as generalized as you find appropriate.</p>
<p>On the surface, opening up this extensibility point is a rather small change, but it’s actually very powerful when used to solve general problems.&#160; In this post, I’ll build a basic INavigationContentLoader that loads pages based on class name rather than project file structure.&#160; In future posts, I hope to explore some more general (and possibly composable) ContentLoaders.</p>
<h3>So… Tell me about this INavigationContentLoader interface.</h3>
<p>Fundamentally, the INavigationContentLoader interface just provides a cancellable asynchronous pattern for loading content based upon a target Uri.&#160; You can set a ContentLoader on the Frame control, which will cause the NavigationService to use your ContentLoader rather than built-in one, which is publicly available as the PageResourceContentLoader.</p>
<p>Here’s what the interface looks like:</p>
<pre class="code"><span style="color: blue">public interface </span><span style="color: #2b91af">INavigationContentLoader
</span>{
    IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, <span style="color: blue">object </span>asyncState);
    <span style="color: blue">void </span>CancelLoad(IAsyncResult asyncResult);
    <span style="color: blue">bool </span>CanLoad(Uri targetUri, Uri currentUri);
    LoadResult EndLoad(IAsyncResult asyncResult);
}</pre>
<p>The basic flow of its use with the Frame control and the NavigationService in the Silverlight SDK is as follows:</p>
<ul>
<li>Frame/NavigationService receives a request to navigate to a Uri </li>
<li>Frame/NavigationService uses its UriMapper to map the Uri it was given to a Uri for use by the content loader </li>
<li>Frame/NavigationService passes the current (post-mapping) Uri to the content loader as well as the target (post-mapping) Uri to the content loader, calling BeginLoad </li>
<li>Frame/NavigationService waits for a callback from the content loader.&#160; If StopLoading() was called, the Frame/NavigationService calls CancelLoad </li>
<li>Upon being called back, the Frame/NavigationService calls EndLoad() on the content loader, receiving a LoadResult
<ul>
<li>If the LoadResult contains a redirect Uri, the Frame/NavigationService begins a new load with that Uri as the target – <strong>without</strong> adding a history entry for the target Uri </li>
<li>Otherwise, the Frame/NavigationService attempts to display the fully-initialized UserControl or Page in the LoadResult </li>
</ul>
</li>
</ul>
<h3>Great, I guess…&#160; Can you show me how to write one?</h3>
<p>Sure!&#160; First, let’s choose a type of ContentLoader we’d like to create.&#160; For this ContentLoader, we’ll begin to break free of the file structure-driven bonds of the existing ContentLoader provided in Silverlight 3.&#160; Instead, we’ll allow navigation to Pages based upon the type name of the Page.&#160; For example, if I have a page called “MyNamespace.MyPage”, I should be able to navigate a frame to the relative Uri “MyNamespace.MyPage” or “/MyNamespace.MyPage” rather than having to point to the XAML file for the Page.</p>
<p>There are two parts to writing a ContentLoader: implementing the interface and implementing IAsyncResult to store the results of your asynchronous operation.&#160; There is ample <a href="http://msdn.microsoft.com/en-us/magazine/cc163467.aspx">documentation for writing an IAsyncResult</a> out there, so I’ll conveniently ignore that for now <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>So, here’s our plan:</p>
<ul>
<li>Implement INavigationContentLoader
<ul>
<li>Write a helper function that extracts a type name from a Uri </li>
<li>Implement CanLoad to check to see if the type specified by the targetUri can be found and has a default constructor </li>
<li>Implement BeginLoad to produce an instance of the page specified by the type in targetUri, store it in an IAsyncResult, and call the consumer’s callback </li>
<li>Implement EndLoad to wrap the page in a LoadResult and return it to the consumer </li>
</ul>
</li>
<li>Implement IAsyncResult
<ul>
<li>Add a “Result” property to hold the constructed page </li>
</ul>
</li>
<li>Use the ContentLoader
<ul>
<li>Specify the ContentLoader in XAML </li>
<li>Update Hyperlinks to navigate using our new Uri scheme </li>
</ul>
</li>
</ul>
<p>Alright, let’s hop to it!</p>
<h4>Implementing INavigationContentLoader</h4>
<p>Let’s start by implementing the interface:</p>
<pre class="code"><span style="color: blue">public class </span><span style="color: #2b91af">TypenameContentLoader </span>: <span style="color: #2b91af">INavigationContentLoader
</span>{
}</pre>
<p>Ok – easy!&#160; Granted, it’s a little empty, but it’s a start!&#160; Now, let’s flesh it out!</p>
<p>To make sense of our Uri scheme, we’ll write a method to extract a Type name from a relative Uri:</p>
<pre class="code"><span style="color: blue">private string </span>GetTypeNameFromUri(<span style="color: #2b91af">Uri </span>uri)
{
    <span style="color: blue">if </span>(!uri.IsAbsoluteUri)
        uri = <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">&quot;dummy:///&quot;</span>, <span style="color: #2b91af">UriKind</span>.Absolute), uri.OriginalString);
    <span style="color: blue">return </span><span style="color: #2b91af">Uri</span>.UnescapeDataString(uri.AbsolutePath.Substring(<span style="color: brown">1</span>));
}</pre>
<p>This method is pretty straightforward.&#160; First, it turns the relative Uri into an absolute one, using a dummy protocol.&#160; Then, it uses the Path of that Uri as the Type name (minus a leading slash and after unescaping any Uri-encoded values (e.g. %20 becomes a space character, so assembly-qualified type names can be used).&#160; The reason we don’t just use the OriginalString on the uri is because the Uri may contain a query string or a fragment (e.g. “TypeName?query=string#fragment”) – in this case we only want the Path in the Uri.</p>
<p>Next, we’ll implement CanLoad, which is called by the Frame/NavigationService before attempting to load.&#160; Here, we’ll check to see that the type exists and has a default constructor – both of which we’ll need in order to create an instance of the page:</p>
<pre class="code"><span style="color: blue">public bool </span>CanLoad(<span style="color: #2b91af">Uri </span>targetUri, <span style="color: #2b91af">Uri </span>currentUri)
{
    <span style="color: blue">string </span>typeName = GetTypeNameFromUri(targetUri);
    <span style="color: #2b91af">Type </span>t = <span style="color: #2b91af">Type</span>.GetType(typeName, <span style="color: blue">false</span>, <span style="color: blue">true</span>);
    <span style="color: blue">if </span>(t == <span style="color: blue">null</span>)
        <span style="color: blue">return false</span>;
    <span style="color: blue">var </span>defaultConstructor = t.GetConstructor(<span style="color: blue">new </span><span style="color: #2b91af">Type</span>[<span style="color: brown">0</span>]);
    <span style="color: blue">if </span>(defaultConstructor == <span style="color: blue">null</span>)
        <span style="color: blue">return false</span>;
    <span style="color: blue">return true</span>;
}</pre>
<p>
  <br />By implementing CanLoad, we can now safely assume (barring any concurrency-related race condition that could arise, but doesn’t apply for the ContentLoader we’re writing in this post because it operates neither statefully nor asynchronously) that the Frame/ContentLoader will only call BeginLoad after making this check.&#160; As such, our BeginLoad can just go ahead and try to create an instance of the type specified in the targetUri.&#160; Then, it must store the instance in an IAsyncResult, invoke the userCallback, and wait for EndLoad to be called:</p>
<p></p>
<pre class="code"><span style="color: blue">public </span><span style="color: #2b91af">IAsyncResult </span>BeginLoad(<span style="color: #2b91af">Uri </span>targetUri, <span style="color: #2b91af">Uri </span>currentUri, <span style="color: #2b91af">AsyncCallback </span>userCallback, <span style="color: blue">object </span>asyncState)
{
    <span style="color: blue">var </span>result = <span style="color: blue">new </span><span style="color: #2b91af">TypenameContentLoaderAsyncResult</span>(asyncState);
    <span style="color: #2b91af">Type </span>t = <span style="color: #2b91af">Type</span>.GetType(GetTypeNameFromUri(targetUri), <span style="color: blue">false</span>, <span style="color: blue">true</span>);
    <span style="color: blue">object </span>instance = <span style="color: #2b91af">Activator</span>.CreateInstance(t);
    result.Result = instance;
    userCallback(result);
    <span style="color: blue">return </span>result;
}</pre>
<p>
  <br />Our implementation of EndLoad will extract the instance of the page from the IAsyncResult and wrap it in a LoadResult.&#160; LoadResult is a simple class we introduced to represent the result of a load operation.&#160; It currently allows for two possible outcomes from a ContentLoader: (1) return/display a Page or UserControl, (2) provide a Uri to which users should be redirected (no history entry for the original page will be created).</p>
<p></p>
<pre class="code"><span style="color: blue">public </span><span style="color: #2b91af">LoadResult </span>EndLoad(<span style="color: #2b91af">IAsyncResult </span>asyncResult)
{
    <span style="color: blue">return new </span><span style="color: #2b91af">LoadResult</span>(((<span style="color: #2b91af">TypenameContentLoaderAsyncResult</span>)asyncResult).Result);
}</pre>
<p>
  <br />The final method of the INavigationContentLoader interface is CancelLoad.&#160; In our case, creating an instance of the page happens synchronously, so cancellation doesn’t really have any meaning or value.&#160; Other ContentLoaders, however, might use this method to stop a download or abort a large operation:</p>
<p></p>
<pre class="code"><span style="color: blue">public void </span>CancelLoad(<span style="color: #2b91af">IAsyncResult </span>asyncResult)
{
    <span style="color: blue">return</span>;
}</pre>
<p>
  <br />And that’s it!&#160; Our Typename-based content loader is complete!&#160; A simple implementation of IAsyncResult will allow us to compile:</p>
<p></p>
<pre class="code"><span style="color: blue">internal class </span><span style="color: #2b91af">TypenameContentLoaderAsyncResult</span>: <span style="color: #2b91af">IAsyncResult
</span>{
    <span style="color: blue">public object </span>Result { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }

    <span style="color: green">// Other IAsyncResult members
</span>}</pre>
<h4>Consuming the ContentLoader</h4>
<p>Consuming our new ContentLoader is as simple as setting the ContentLoader property on your Frame in XAML:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame </span><span style="color: red">xmlns</span><span style="color: blue">:</span><span style="color: red">loader</span><span style="color: blue">=&quot;clr-namespace:TypenameContentLoader.ContentLoader&quot;
                  </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;ContentFrame&quot;
</span><span style="color: blue">                  </span><span style="text-decoration: underline"><strong><em><span style="color: red">Source</span><span style="color: blue">=&quot;/TypenameContentLoader.Views.Home&quot;</span></em></strong></span><span style="color: blue">&gt;
<strong><em>                  <span style="text-decoration: underline">&lt;</span></em></strong></span><strong><em><span style="text-decoration: underline"><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span></span></em></strong><strong><em><span><span style="text-decoration: underline">&gt;
</span>                      <span style="text-decoration: underline">&lt;loader</span></span><span style="text-decoration: underline"><span style="color: blue">:</span><span style="color: #a31515">TypenameContentLoader </span></span></em></strong><strong><em><span style="color: blue"><span style="text-decoration: underline">/&gt;
</span>                  <span style="text-decoration: underline">&lt;/</span></span><span style="text-decoration: underline"><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame.ContentLoader</span></span></em></strong><span style="color: blue"><strong><em><span style="text-decoration: underline">&gt;</span></em></strong>
&lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame</span><span style="color: blue">&gt;
</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>You’ll note that in addition to setting the ContentLoader, I’ve set the source for the Frame control to match our new Uri scheme.&#160; We must also do the same for other hyperlinks in the application:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">HyperlinkButton </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;Link1&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinkStyle</span><span style="color: blue">}&quot;
                 </span><span style="color: red"><strong><em><span style="text-decoration: underline">NavigateUri</span></em></strong></span><span style="color: blue"><strong><em><span style="text-decoration: underline">=&quot;/TypenameContentLoader.Views.Home&quot;</span></em></strong> </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; </span><span style="color: red">Content</span><span style="color: blue">=&quot;home&quot;/&gt;
</span><span style="color: blue">
&lt;</span><span style="color: #a31515">HyperlinkButton </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;Link2&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinkStyle</span><span style="color: blue">}&quot;
                 </span><span style="color: red"><span style="text-decoration: underline"><strong><em>NavigateUri</em></strong></span></span><span style="color: blue"><span style="text-decoration: underline"><strong><em>=&quot;/TypenameContentLoader.Views.About, TypenameContentLoader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null&quot;</em></strong></span> </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; </span><span style="color: red">Content</span><span style="color: blue">=&quot;about&quot;/&gt;
</span><span style="color: blue">
&lt;</span><span style="color: #a31515">HyperlinkButton </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;Link3&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinkStyle</span><span style="color: blue">}&quot;
                 </span><span style="color: red"><strong><em><span style="text-decoration: underline">NavigateUri</span></em></strong></span><span style="color: blue"><strong><em><span style="text-decoration: underline">=&quot;/TypenameContentLoader.Views.ParameterizedPage?a=100&amp;amp;b=1000&quot;</span></em></strong>
                 </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; </span><span style="color: red">Content</span><span style="color: blue">=&quot;parameterized?a=100&amp;amp;b=1000&quot;/&gt;
</span></pre>
<p>And there you have it!&#160; The application is fully configured to use the new ContentLoader.&#160; You’ll notice that the Frame will happily pass along the complex Uris in all three of the hyperlinks above, and the loader will load them correctly.&#160; Query string values still get parsed by the navigation service, and all is well with the world <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Ok, so now I can build a ContentLoader – can I actually see the code?</h3>
<p>Yep, and I’ll do you one better!&#160; You can also try the <a href="http://www.davidpoll.com/Samples/TypenameContentLoader/TypenameContentLoaderTestPage.html">live sample</a>!</p>
<ul>
<li><a href="http://www.davidpoll.com/Samples/Download/TypenameContentLoader.zip">TypenameContentLoader source</a> </li>
<li><a href="http://www.davidpoll.com/Samples/TypenameContentLoader/TypenameContentLoaderTestPage.html">Live sample</a> </li>
</ul>
<p>And, just to prove that query strings “just work”, try this link into the application with a long list of key/value pairs that get used by the page:</p>
<p align="left"><a href="http://www.davidpoll.com/Samples/TypenameContentLoader/TypenameContentLoaderTestPage.html#/TypenameContentLoader.Views.ParameterizedPage?a&amp;b=foo&amp;c=bar&amp;d=Hello, world!&amp;e=Why not?&amp;f=Very cool&amp;g=1000&amp;h&amp;i=1.100&amp;j=Woohoo!&amp;David=Poll&amp;davidpoll.com=is cool" target="_blank"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="A long query string with the new content loader" border="0" alt="A long query string with the new content loader" src="http://www.davidpoll.com/Images/OpeningupSilverlight4NavigationIntroduct_904D/image.png" width="629" height="484" /></a></p>
<p align="left">Feel free to play around with it and let me know what you think!</p>
<p align="left">(Also note the screenshot above using Google Chrome – now a supported browser with Silverlight 4!)</p>
<h3>Ok, so all of this is cool, but why is it useful?&#160; What’s next?</h3>
<p>This Typename-based content loader is a neat trick to try, but its usefulness is still pretty limited.&#160; The extensibility point itself, however, is very powerful.&#160; Instead of having to come up with hacks and workarounds for things like on-demand downloading of assemblies containing pages as I did before, we can bake that logic right into a content loader!&#160; If you are an adherent of the MVVM pattern, you can use your content loader to connect your view to your model.&#160; If all you need to do is specify constructor parameters to your pages, you now have that option!&#160; If you need to pre-load data from a web service before navigating to a page, a content loader can help!</p>
<p>The ContentLoader extensibility point introduced in the Silverlight 4 beta really opens up Silverlight Navigation, allowing you to interject in the page loading process and enabling you to make navigation work with whatever framework or application structure you choose.</p>
<p>I’ve got a bunch of ideas for useful ContentLoaders that I’ll explore (and hopefully blog about) going forward.&#160; If you’ve got ideas, questions, or feedback, please let me know!&#160; I look forward to hearing from you!</p>
<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.davidpoll.com/2009/11/30/opening-up-silverlight-4-navigation-introduction-to-inavigationcontentloader/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Relative hyperlinks with Silverlight navigation</title>
		<link>http://www.davidpoll.com/2009/09/20/relative-hyperlinks-with-silverlight-navigation/</link>
		<comments>http://www.davidpoll.com/2009/09/20/relative-hyperlinks-with-silverlight-navigation/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 05:39:00 +0000</pubDate>
		<dc:creator>david.poll</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Dynamic Navigation]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Relative Links]]></category>
		<category><![CDATA[Silverlight 3]]></category>

		<guid isPermaLink="false">http://www.davidpoll.com/2009/09/20/relative-hyperlinks-with-silverlight-navigation/</guid>
		<description><![CDATA[If you haven’t noticed already, I happen to like the Navigation feature in Silverlight quite a bit (I wonder why? ).  In my other posts on Navigation, I’ve spent some time exploring how you can navigate to Pages in assemblies other than the main application assembly and how those assemblies can be loaded on-demand (granted, [...]]]></description>
			<content:encoded><![CDATA[<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_start --><p>If you haven’t noticed already, I happen to like the Navigation feature in Silverlight quite a bit (I wonder why? <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ).  In my <a href="http://www.davidpoll.com/tag/navigation/">other posts on Navigation</a>, I’ve spent some time exploring how you can navigate to Pages in assemblies other than the main application assembly and how those assemblies can be loaded on-demand (granted, it uses some workarounds, but it gets us where we want to go!).</p>
<p>This is all well and good, but it presents an annoying problem that impacts the maintainability of such code.  Specifically, it forces every hyperlink within each of the external assemblies to know how to refer to its assembly by name (this is akin to the problem with absolute URLs in hyperlinks on web pages – those links become tightly coupled to the page for which they were created, and can’t be copied into other projects).</p>
<p>Technically, almost all Uris used by the navigation framework today are relative Uris (unless UriMappings are used to turn absolute ones into relative ones), but they are application-relative and never Page-relative.  This means that if you have a page at “/Views/Page1.xaml” and want to link to another page at “/Views/Page2.xaml” from within Page1, you must refer to the entire path (“/Views/Page2.xaml”) rather than just the relative path to the other page (e.g. “Page2.xaml” or “./Page2.xaml”).</p>
<p>In this post, we’ll look at a way to allow Page-relative navigation within your Silverlight Pages.  The approach I’ll use will take advantage of the INavigate interface that was added in Silverlight 3 and the HyperlinkButton control that uses this interface to perform navigation when clicked.</p>
<p>The INavigate interface looks like this:</p>
<pre class="code"><span style="color: blue">public interface </span><span style="color: #2b91af">INavigate
</span>{
    <span style="color: green">// Methods
    </span><span style="color: blue">bool </span>Navigate(<span style="color: #2b91af">Uri </span>source);
}</pre>
<p>It’s a simple interface with a simple purpose: allow a component to provide a way to handle navigation to a Uri.  Right now, the only component built into Silverlight that actually takes advantage of it is the HyperlinkButton control.  We use this control quite often in Navigation-enabled applications, since it allows us to target a particular Frame control to navigate to a Page by Uri.  In the Silverlight Navigation Application project template, you’ll see XAML like this:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">="<strong><em><span style="text-decoration: underline;">ContentFrame</span></em></strong>" </span><span style="color: red">Style</span><span style="color: blue">="{</span><span style="color: #a31515">StaticResource </span><span style="color: red">ContentFrameStyle</span><span style="color: blue">}"
                  </span><span style="color: red">Source</span><span style="color: blue">="/Home" </span><span style="color: red">Navigated</span><span style="color: blue">="ContentFrame_Navigated" </span><span style="color: red">NavigationFailed</span><span style="color: blue">="ContentFrame_NavigationFailed"&gt;
&lt;/</span><span style="color: #a31515">navigation</span><span style="color: blue">:</span><span style="color: #a31515">Frame</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>And:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">HyperlinkButton </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">="Link2" </span><span style="color: red">Style</span><span style="color: blue">="{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinkStyle</span><span style="color: blue">}"
                 </span><span style="color: red">NavigateUri</span><span style="color: blue">="/About" </span><span style="color: red"><strong><em><span style="text-decoration: underline;">TargetName</span></em></strong></span><span style="color: blue"><strong><em><span style="text-decoration: underline;">="ContentFrame</span></em></strong>" </span><span style="color: red">Content</span><span style="color: blue">="about"/&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>This all works because the Frame control implements INavigate.  In other words, there’s no magic there – you can use it too!  Here’s the way the HyperlinkButton works when you’re trying to target an INavigate (approximately <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ):</p>
<ul>
<li>For each parent FrameworkElement going up the visual tree from the HyperlinkButton…
<ul>
<li>Check to see if the FrameworkElement is an INavigate and that its name matches TargetName (ignored if TargetName is null or empty)
<ul>
<li>If so, call INavigate.Navigate() on the FrameworkElement</li>
<li>Otherwise, recursively search for an INavigate that’s properly named within each of the children of the FrameworkElement</li>
</ul>
</li>
<li>If no properly named INavigate was found, keep moving up the visual tree</li>
</ul>
</li>
</ul>
<p>In other words, the HyperlinkButton will search its way up and down the visual tree (technically doing a pre-order breadth-first search from each parent of the HyperlinkButton, working its way up the visual tree) for an appropriate INavigate to call.</p>
<h2>So, what does all this INavigate stuff mean to me?</h2>
<p>With that technical detail out of the way, the question that arises is: how can we use this to enable Page-relative navigation?  Well, the reason navigation of a Frame works within Pages today is because the Frame control implements INavigate, and the HyperlinkButton works its way up the visual tree until it finds this.</p>
<p>For our purposes, this is great, since it means we can intercept the call to INavigate.Navigate() by implementing the interface somewhere between the HyperlinkButton and the Frame.  There’s a convenient place for this, since applications that use Page/Frame and HyperlinkButtons within those pages have a visual tree like this:</p>
<ul>
<li>Application
<ul>
<li>Layout
<ul>
<li><strong><em>Frame</em></strong>
<ul>
<li><strong><em><span style="text-decoration: underline;">Page</span></em></strong>
<ul>
<li><strong><em>HyperlinkButton</em></strong></li>
<li>Other controls</li>
</ul>
</li>
</ul>
</li>
<li>Other Controls</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>What I’m suggesting is that the Page we navigate to implement INavigate and turn page-relative Uri’s into application-relative Uri’s before handing them off the NavigationService (or the Frame) to actually perform the navigation.</p>
<p>I’ve gone ahead and extended my DynamicNavigation library to make DynamicPage implement INavigate to do what we want, but you could do the same on any subclass of Page (including every one of your Pages if you didn’t want a common base class).  Here’s my simple implementation (with a switch to turn off this feature on DynamicPages):</p>
<pre class="code"><span style="color: blue">public bool </span>RelativeLinks
{
    <span style="color: blue">get </span>{ <span style="color: blue">return </span>(<span style="color: blue">bool</span>)GetValue(RelativeLinksProperty); }
    <span style="color: blue">set </span>{ SetValue(RelativeLinksProperty, <span style="color: blue">value</span>); }
}

<span style="color: blue">public static readonly </span><span style="color: #2b91af">DependencyProperty </span>RelativeLinksProperty =
    <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">"RelativeLinks"</span>, <span style="color: blue">typeof</span>(<span style="color: blue">bool</span>), <span style="color: blue">typeof</span>(<span style="color: #2b91af">DynamicPage</span>), <span style="color: blue">new </span><span style="color: #2b91af">PropertyMetadata</span>(<span style="color: blue">true</span>));

<span style="color: blue">private static readonly </span><span style="color: #2b91af">Uri </span>basePlaceHolderUri = <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"none:///"</span>, <span style="color: #2b91af">UriKind</span>.Absolute);

<span style="color: blue">#region </span>INavigate Members

<span style="color: blue">public bool </span>Navigate(<span style="color: #2b91af">Uri </span>navigateUri)
{
    <span style="color: blue">string </span>original = navigateUri.OriginalString;
    <span style="color: blue">if </span>(RelativeLinks &amp;&amp; !navigateUri.IsAbsoluteUri &amp;&amp; !original.StartsWith(<span style="color: #a31515">"/"</span>))
    {
        <span style="color: #2b91af">Uri </span>result;
        <span style="color: blue">if </span>(NavigationService.CurrentSource.IsAbsoluteUri)
        {
            result = <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(NavigationService.CurrentSource, navigateUri);
        }
        <span style="color: blue">else
        </span>{
            <span style="color: #2b91af">Uri </span>baseUri = <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(basePlaceHolderUri, NavigationService.CurrentSource);
            result = <span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(<span style="color: #a31515">"/" </span>+ basePlaceHolderUri.MakeRelativeUri(<span style="color: blue">new </span><span style="color: #2b91af">Uri</span>(baseUri, navigateUri)).OriginalString,
                <span style="color: #2b91af">UriKind</span>.Relative);
        }
        <span style="color: blue">return </span>NavigationService.Navigate(result);
    }
    <span style="color: blue">else
    </span>{
        <span style="color: blue">return </span>NavigationService.Navigate(navigateUri);
    }
}

<span style="color: blue">#endregion</span></pre>
<p>Now, within the page, you can use Page-relative Uri’s on HyperlinkButtons.  All you need to do is avoid setting a TargetName (either through a style or directly on the HyperlinkButton), and the Page will handle the navigation!</p>
<p>Page-relative Uri’s can take a variety of forms.  Assuming the Page you’re currently on is “/MyLibrary;component/Views/Main/Page1.xaml”, the following transformations will occur (as an example):</p>
<ul>
<li>“Page2.xaml” –&gt; “/MyLibrary;component/Views/Main/Page2.xaml”</li>
<li>“./Page2.xaml” –&gt; “/MyLibrary;component/Views/Main/Page2.xaml”</li>
<li>“../Page3.xaml” –&gt; “/MyLibrary;component/Views/Page3.xaml”</li>
<li>“../Secondary/Page3.xaml” –&gt; “/MyLibrary;component/Views/Secondary/Page3.xaml”</li>
<li>“../../BasePage.xaml” –&gt; “/MyLibrary;component/BasePage.xaml”</li>
<li>“SubMain/Page4.xaml” –&gt; “/MyLibrary;component/Views/Main/SubMain/Page4.xaml”</li>
<li>“SubMain/Page4.xaml?a=b&amp;c=d” –&gt; “/MyLibrary;component/Views/Main/SubMain/Page4.xaml?a=b&amp;c=d”</li>
<li>“/MyLibrary;component/Views/Main/Page5.xaml” –&gt; “/MyLibrary;component/Views/Main/Page5.xaml” (no change)</li>
</ul>
<h2>Cool!  Can I see it in action?</h2>
<p>Of course! <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   As always, you can play around with a running app that does this here:</p>
<p><a href="http://www.davidpoll.com/Samples/RelativeNavigation/DynamicNavigationApplicationTestPage.html#/DynamicallyLoadedLibrary;component/CSDynamicPage.dyn.xaml" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Live sample of page-relative navigation" src="http://www.davidpoll.com/Images/RelativehyperlinkswithSilverlightnavigat_1274C/image.png" border="0" alt="Live sample of page-relative navigation" width="644" height="479" /></a></p>
<p>Click the link at the bottom of that page to peform a relative navigation that should take you on a journey between a number of pages – all of which navigate using relative navigation.</p>
<p>For reference, here is the file structure for the sample application.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="File structure of the sample application." src="http://www.davidpoll.com/Images/RelativehyperlinkswithSilverlightnavigat_1274C/image_3.png" border="0" alt="File structure of the sample application." width="268" height="255" /> </p>
<h2>So, what’s your point?</h2>
<p>Well, to sum it up – being able to do page-relative navigation increases the portability of your Pages.  It’s especially useful if you use it in conjunction with UriMapping.  With the technique above, the “relative-ness” refers to the user-facing Uri.  This means that you can create UriMappings in order to create a “virtual” file structure, and all of your relative links should continue to work (and new ones might be possible!).  Give it a shot and let me know what you think!  I’m continuing to experiment with Navigation, always on the lookout for things that might improve the experience when working with it.</p>
<h2>Enough already!  Give me the goods!</h2>
<p>Patience!  You didn’t really think I’d leave you hanging, did you?  Here you go:</p>
<ul>
<li><a href="http://www.davidpoll.com/Download/DynamicNavigation.zip">DynamicNavigation libraries</a> (see my other posts for an introduction to what it provides and how to use it – <a href="http://www.davidpoll.com/2009/07/14/silverlight-3-navigation-navigating-to-pages-in-dynamically-loaded-assemblies/">1</a>, <a href="http://www.davidpoll.com/2009/07/20/on-demand-loading-of-assemblies-with-silverlight-navigation/">2</a>)</li>
<li><a href="http://www.davidpoll.com/Download/RelativeNavigationSample.zip">Sample Source</a></li>
</ul>
<h2>Stop talking to yourself!</h2>
<p>Okay. <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.davidpoll.com/2009/09/20/relative-hyperlinks-with-silverlight-navigation/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>On-demand loading of assemblies with Silverlight Navigation</title>
		<link>http://www.davidpoll.com/2009/07/20/on-demand-loading-of-assemblies-with-silverlight-navigation/</link>
		<comments>http://www.davidpoll.com/2009/07/20/on-demand-loading-of-assemblies-with-silverlight-navigation/#comments</comments>
		<pubDate>Mon, 20 Jul 2009 22:01:00 +0000</pubDate>
		<dc:creator>david.poll</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[BusyIndicator]]></category>
		<category><![CDATA[Dynamic Navigation]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Silverlight 3]]></category>

		<guid isPermaLink="false">http://www.davidpoll.com/2009/07/21/on-demand-loading-of-assemblies-with-silverlight-navigation/</guid>
		<description><![CDATA[As those of you who’ve been reading my blog may know, I’ve been spending a bit of time with some enhancements to navigation in Silverlight surrounding the use of dynamically-loaded assemblies.&#160; I’ve still got a bunch of things I’d like to try to implement, but in the meantime I thought I’d share what I’ve got [...]]]></description>
			<content:encoded><![CDATA[<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_start --><p>As those of you who’ve been reading my blog may know, I’ve been spending a bit of time with some enhancements to navigation in Silverlight surrounding the use of dynamically-loaded assemblies.&#160; I’ve still got a bunch of things I’d like to try to implement, but in the meantime I thought I’d share what I’ve got so far.</p>
<p>Now that I have a mechanism for navigating to Pages in dynamically-loaded assemblies in Silverlight, the question arises: how can I improve the user and developer experience around partitioning applications in this way?</p>
<p>In particular, this is the flow I’d like to be able to create:</p>
<ul>
<li>Developer knows the set of Pages his user will be able to navigate to, and partitions them into assemblies that he will load at runtime </li>
<li>Furthermore, the developer knows the dependencies those assemblies have on other dynamically-loaded assemblies (e.g. multiple assemblies contain Pages that use DataGrid, but System.Windows.Controls.Data should be shared/downloaded when the first of those assemblies is downloaded) </li>
<li>The user is presented with some sort of navigation UI (e.g. HyperlinkButtons, buttons that call Frame.Navigate(), etc.) </li>
<li>When the user requests a page in an assembly that has not yet been downloaded, it should be automatically downloaded, and navigation with the Frame should only complete once the Page can be loaded. </li>
</ul>
<p>With this on-demand loading behavior, deep-linking into applications with dynamically-loaded assemblies can be re-enabled (you’ll notice if you try to deep-link into my sample from my <a href="http://www.davidpoll.com/?p=92">previous post</a> about dynamically-loaded assemblies, you get an exception, since the assembly hasn’t been loaded yet).</p>
<p>I’m developing some utilities that will make this flow easier to accomplish.&#160; Please note that at this point all of the API, etc. is subject to change, and I’m definitely not making any assurances around bugs, quality, or anything of the sort, but I thought I’d share what I’ve been working on and start getting some feedback from you folks!</p>
<p>Anyhoo, let’s take this step by step:</p>
<p><strong><span style="font-size: medium">Dividing an application into multiple assemblies</span></strong></p>
<p>This is fairly straightforward, and something I’m sure most of you have been doing for a long time.&#160; For our purposes, there are a number of things to consider:</p>
<ul>
<li>Pages in these assemblies that will be dynamically loaded should use the DynamicPage and DynamicPageShim (or some other workaround you may have come up with) described in my <a href="http://www.davidpoll.com/?p=92">earlier post</a> </li>
<li>Any dynamically-loaded assemblies need to be in a place accessibly using the WebRequest APIs in Silverlight.&#160; I usually put them in my ClientBin folder, and I used a post-build task to copy any dlls for those assemblies into the correct folder (feel free to see my Sample project for an example of this) </li>
<li>The libraries I’ve built support loading DLLs as well as XAP and ZIP files with dlls in them. Just using DLLs is probably the easiest way to go, but using ZIP or XAP files will keep the transfer time/size small. </li>
<li>Remember to take careful note of any dependencies between the libraries.&#160; You’ll need to make sure they’re all loaded into your application before attempting to use the assemblies. </li>
</ul>
<p>One thing I might do in the future is (attempt to) make a project template that will create a XAP class library that places the XAP in the ClientBin folder for you.&#160; I’m still experimenting with how to do this, but it’s still worth noting that using XAPs can be problematic if you’re sharing libraries (VS will automatically package shared assemblies into your XAP, so you might end up with copies of System.Windows.Controls.Navigation.dll in 3 or 4 XAPs, and since they’re all packaged up with the rest of the assemblies, you’ll end up downloading the same DLL multiple times.</p>
<p><strong><span style="font-size: medium">Describing how to load assemblies dynamically</span></strong></p>
<p>I’ve created a little utility that I call “DynamicLoader,” which allows you to declare, in XAML, where your dynamic DLLs can be downloaded from and their interdependencies.&#160; In my App.xaml, I specify the various libraries that may be loaded dynamically (incidentally, some of these libraries are also in my XAP, and the loader will use the ones built into the XAP rather than re-downloading them automatically).&#160; I also describe the various interdependencies between my libraries.&#160; Some are unnecessary (because the dependencies are already in the XAP), but I chose to be explicit for some of the more complex ones to remove all doubt.&#160; An example (from my sample project) can be seen below.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">DynamicLoader </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Key</span><span style="color: blue">=&quot;loader&quot;&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;DynamicallyLoadedLibrary&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;./DynamicallyLoadedLibrary.dll&quot; /&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;DynamicallyLoadedLibraryVB&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;./DynamicallyLoadedLibraryVB.dll&quot; /&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;LargeDynamicallyLoadedLibrary&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;./LargeDynamicallyLoadedLibrary.dll&quot;&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls&quot; /&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.Data&quot; /&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.Data.DataForm.Toolkit&quot; /&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.Data.Input&quot; /&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.DataVisualization.Toolkit&quot; /&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.Navigation&quot; /&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Data&quot; /&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.ComponentModel.DataAnnotations&quot; /&gt;
    &lt;/</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;./System.Windows.Controls.dll&quot; /&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.Data&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;./System.Windows.Controls.Data.dll&quot;&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.ComponentModel.DataAnnotations&quot; /&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.Data.Input&quot; /&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Data&quot; /&gt;
    &lt;/</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.Data.DataForm.Toolkit&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;./System.Windows.Controls.Data.DataForm.Toolkit.dll&quot;&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.ComponentModel.DataAnnotations&quot; /&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Data&quot; /&gt;
    &lt;/</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.Data.Input&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;./System.Windows.Controls.Data.Input.dll&quot;&gt;
        &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">Dependency </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.ComponentModel.DataAnnotations&quot; /&gt;
    &lt;/</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.DataVisualization.Toolkit&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;./System.Windows.Controls.DataVisualization.Toolkit.dll&quot; /&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Controls.Navigation&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;./System.Windows.Controls.Navigation.dll&quot; /&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.Windows.Data&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;./System.Windows.Data.dll&quot; /&gt;
    &lt;</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">AssemblyDescription </span><span style="color: red">AssemblyName</span><span style="color: blue">=&quot;System.ComponentModel.DataAnnotations&quot;
                              </span><span style="color: red">Location</span><span style="color: blue">=&quot;System.ComponentModel.DataAnnotations.dll&quot; /&gt;
&lt;/</span><span style="color: #a31515">load</span><span style="color: blue">:</span><span style="color: #a31515">DynamicLoader</span><span style="color: blue">&gt;</span></pre>
<p>The Location specified in each AssemblyDescription is a URI.&#160; In this case, all of my dlls are in my ClientBin directory, so they all begin with “./”, but these could be any URI that can be reached by the Silverlight application.&#160; Furthermore, if you wish to use the new ClientHttp networking stack to do the downloading, you can choose to do so (as part of the AssemblyDescription).</p>
<p>The loader will asynchronously load any requested library (by name), and will only fire Loaded events once all of each assembly’s dependencies have been loaded.&#160; This allows us to know when it’s safe to try to navigate to a Page in a dynamically-loaded assembly.</p>
<p><strong><span style="font-size: medium">Creating Navigation UI</span></strong></p>
<p>Nothing too special to share here.&#160; HyperlinkButtons use the exact same URI scheme as before (for navigating to pages in <a href="http://www.davidpoll.com/2009/07/12/silverlight-3-navigation-navigating-to-pages-in-referenced-assemblies/">referenced</a>/<a href="http://www.davidpoll.com/?p=92">dynamically-loaded</a> assemblies).&#160; Here’s what my XAML for my navigation bar looks like:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">Border </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;LinksBorder&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinksBorderStyle</span><span style="color: blue">}&quot;&gt;
    &lt;</span><span style="color: #a31515">StackPanel </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;LinksStackPanel&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinksStackPanelStyle</span><span style="color: blue">}&quot;&gt;

        &lt;</span><span style="color: #a31515">HyperlinkButton </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;Link1&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinkStyle</span><span style="color: blue">}&quot;
                     </span><span style="color: red">NavigateUri</span><span style="color: blue">=&quot;/Home&quot; </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; </span><span style="color: red">Content</span><span style="color: blue">=&quot;home&quot;/&gt;

        &lt;</span><span style="color: #a31515">Rectangle </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;Divider1&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">DividerStyle</span><span style="color: blue">}&quot;/&gt;

        &lt;</span><span style="color: #a31515">HyperlinkButton </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;Link2&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinkStyle</span><span style="color: blue">}&quot;
                     </span><span style="color: red">NavigateUri</span><span style="color: blue">=&quot;/About&quot; </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; </span><span style="color: red">Content</span><span style="color: blue">=&quot;about&quot;/&gt;

        &lt;</span><span style="color: #a31515">Rectangle </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;Divider2&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">DividerStyle</span><span style="color: blue">}&quot;/&gt;

        &lt;</span><span style="color: #a31515">HyperlinkButton </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;csharp&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinkStyle</span><span style="color: blue">}&quot; </span><span style="color: red">IsEnabled</span><span style="color: blue">=&quot;True&quot;
                     </span><span style="color: red">NavigateUri</span><span style="color: blue">=&quot;/DynamicallyLoadedLibrary;component/CSDynamicPage.dyn.xaml&quot; </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; </span><span style="color: red">Content</span><span style="color: blue">=&quot;C# Class Library&quot;/&gt;

        &lt;</span><span style="color: #a31515">Rectangle </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;Divider3&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">DividerStyle</span><span style="color: blue">}&quot;/&gt;

        &lt;</span><span style="color: #a31515">HyperlinkButton </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;vb&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinkStyle</span><span style="color: blue">}&quot; </span><span style="color: red">IsEnabled</span><span style="color: blue">=&quot;True&quot;
                     </span><span style="color: red">NavigateUri</span><span style="color: blue">=&quot;/DynamicallyLoadedLibraryVB;component/VBDynamicPage.dyn.xaml&quot; </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; </span><span style="color: red">Content</span><span style="color: blue">=&quot;VB Class Library&quot;/&gt;

        &lt;</span><span style="color: #a31515">Rectangle </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;Divider4&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">DividerStyle</span><span style="color: blue">}&quot;/&gt;

        &lt;</span><span style="color: #a31515">HyperlinkButton </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;large&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">LinkStyle</span><span style="color: blue">}&quot; </span><span style="color: red">IsEnabled</span><span style="color: blue">=&quot;True&quot;
                     </span><span style="color: red">NavigateUri</span><span style="color: blue">=&quot;/LargeDynamicallyLoadedLibrary;component/LargeDynamicPage.dyn.xaml&quot; </span><span style="color: red">TargetName</span><span style="color: blue">=&quot;ContentFrame&quot; </span><span style="color: red">Content</span><span style="color: blue">=&quot;Large Class Library&quot;/&gt;
    &lt;/</span><span style="color: #a31515">StackPanel</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">Border</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>Again, nothing too scary here – the XAML remains identical to its form without the dynamically-loaded libraries.</p>
<p><strong><span style="font-size: medium">Adding on-demand navigation</span></strong></p>
<p>The other important piece of this puzzle is a Frame control that uses the loader to ensure that dynamically-loaded libraries are loaded into the AppDomain before attempting to navigate to pages within those libraries.&#160; I’ve provided a derived Frame class (DynamicNavigation.Utilities.Controls.Frame) that does precisely this.&#160; As with my DynamicPage class, you should expect a few quirks, since the Frame class from which it derives doesn’t have any virtual methods.&#160; Don’t cast my Frame to a System.Windows.Controls.Frame if you don’t want to get a bunch of extra events for Loading, Loaded, etc.&#160; Also, since I couldn’t replace the NavigationService, if you subscribe to events on that service, you’ll see a large number of extra events being raised.&#160; Neither of these eccentricities should hamper functionality, but you may see some unexpected activity if you watch those events!</p>
<p>My Frame class takes an DynamicLoader and delegates all loading of dynamic libraries to it.&#160; Here’s what my XAML declaration of the Frame looks like (plus or minus some extraneous attributes):</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">dnav</span><span style="color: blue">:</span><span style="color: #a31515">Frame </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;ContentFrame&quot; </span><span style="color: red">Style</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">ContentFrameStyle</span><span style="color: blue">}&quot;
            </span><span style="color: red">DynamicLoader</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">StaticResource </span><span style="color: red">loader</span><span style="color: blue">}&quot;
            </span><span style="color: red">Source</span><span style="color: blue">=&quot;/Home&quot;&gt;
    &lt;</span><span style="color: #a31515">dnav</span><span style="color: blue">:</span><span style="color: #a31515">Frame.UriMapper</span><span style="color: blue">&gt;
        &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapper</span><span style="color: blue">&gt;
            &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapping </span><span style="color: red">Uri</span><span style="color: blue">=&quot;&quot; </span><span style="color: red">MappedUri</span><span style="color: blue">=&quot;/Views/Home.xaml&quot;/&gt;
            &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapping </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/{a};component/{p}&quot; </span><span style="color: red">MappedUri</span><span style="color: blue">=&quot;/{a};component/{p}&quot; /&gt;
            &lt;</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapping </span><span style="color: red">Uri</span><span style="color: blue">=&quot;/{pageName}&quot; </span><span style="color: red">MappedUri</span><span style="color: blue">=&quot;/Views/{pageName}.xaml&quot;/&gt;
        &lt;/</span><span style="color: #a31515">uriMapper</span><span style="color: blue">:</span><span style="color: #a31515">UriMapper</span><span style="color: blue">&gt;
    &lt;/</span><span style="color: #a31515">dnav</span><span style="color: blue">:</span><span style="color: #a31515">Frame.UriMapper</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">dnav</span><span style="color: blue">:</span><span style="color: #a31515">Frame</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>And that’s it!&#160; With my custom Frame class, it take <strong>*zero*</strong> code to get dynamic loading up and running – only XAML is necessary.&#160; Attach an Activity control to the loader, and you’re hot to trot!</p>
<p><strong><span style="font-size: medium">In Conclusion</span></strong></p>
<p>Well, there you have it!&#160; I’d like to remind folks that none of the APIs here are intended to be concrete, and I make no guarantees of quality – I’m just trying to demonstrate how it can be done, and if the interest is there, I’ll keep investing some time in exploring this.&#160; I’ve got a bunch of ideas for where I can go from here, things I’d like to change/improve, and I look forward to playing some more with these prototypes.</p>
<p>Without further ado, here are the links I’m sure you’re all waiting for:</p>
<ul>
<li><a href="http://www.davidpoll.com/Download/DynamicNavigation.zip">DynamicNavigation libraries</a> (for your consumption) </li>
<li><a href="http://www.davidpoll.com/Samples/OnDemandDownload/DynamicNavigationApplicationTestPage.html">Live Sample</a> </li>
<li><a href="http://www.davidpoll.com/Samples/Download/OnDemandNavigationSample.zip">Sample Source</a> </li>
</ul>
<p><strong><span style="font-size: medium">What’s next?</span></strong></p>
<p>Well, I’ve got a lot of ideas, and I’d love to hear some from you all.&#160; Here are some of mine (not making any promises – I’m just experimenting with these):</p>
<ul>
<li>Cache to IsoStore – downloaded libraries could be stored in Isolated Storage and loaded from there if they’re already on the machine </li>
<li>Install – When the application is taken out of browser, automatically download the assemblies to Isolated Storage and load from there, allowing the entire application to be run offline </li>
<li>URI scheme/custom loading – I’d love to be able to just specify the whole deal in a URI to a page, such as “pack://http:,,www.davidpoll.com,Samples,ClientBin,MyLibrary.dll;component/Page2.dyn.xaml” and not need the big manifest with assembly name/location mappings and dependencies. </li>
<li>Dependencies for particular URIs – allows the Frame control to pre-load assemblies before a particular page is loaded, even if the page is a local one (thanks, Austin, for this idea!) </li>
</ul>
<p>Anyway, I’ve got a thousand other ideas racing through my mind right now, but those are just a few.&#160; What do you think?&#160; Is there anything you dislike about my approach or anything you particularly like?&#160; Speak up!</p>
<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.davidpoll.com/2009/07/20/on-demand-loading-of-assemblies-with-silverlight-navigation/feed/</wfw:commentRss>
		<slash:comments>49</slash:comments>
		</item>
		<item>
		<title>Silverlight 3 Navigation: Adding transitions to the Frame control</title>
		<link>http://www.davidpoll.com/2009/07/19/silverlight-3-navigation-adding-transitions-to-the-frame-control/</link>
		<comments>http://www.davidpoll.com/2009/07/19/silverlight-3-navigation-adding-transitions-to-the-frame-control/#comments</comments>
		<pubDate>Sun, 19 Jul 2009 22:03:26 +0000</pubDate>
		<dc:creator>david.poll</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Silverlight 3]]></category>
		<category><![CDATA[Silverlight Toolkit]]></category>

		<guid isPermaLink="false">http://www.davidpoll.com/2009/07/19/silverlight-3-navigation-adding-transitions-to-the-frame-control/</guid>
		<description><![CDATA[Continuing with my recent theme of enhancing the built-in support for Navigation in Silverlight 3, I thought I’d use this post to look briefly at enhancing user experience during navigation.&#160; On the surface, the Frame control is pretty unexciting from a UX perspective – its job is really just to display pages as a result [...]]]></description>
			<content:encoded><![CDATA[<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_start --><p>Continuing with my recent theme of enhancing the built-in support for Navigation in Silverlight 3, I thought I’d use this post to look briefly at enhancing user experience during navigation.&#160; On the surface, the Frame control is pretty unexciting from a UX perspective – its job is really just to display pages as a result of requests to navigate (either through the browser’s address bar, responding to HyperlinkButton clicks, or direct calls to Frame.Navigate()).&#160; It has barely any UI of its own, and can usually be thought of as an enhanced ContentControl (incidentally, it is one!).</p>
<p>Most of the time, all the Frame is doing is displaying a Page, and this (in my opinion at least) is an appropriate presentation – the Frame shouldn’t get in the way of displaying my Pages.&#160; Where I do want the Frame to intervene now and then is during page changes, allowing me to provide rich transitions when navigating from Page to Page.&#160; The Frame control provided in the Silverlight 3 SDK doesn’t do anything for us as far as transitions go out of the box, but with a little templating magic and the <a href="http://silverlight.codeplex.com/">Silverlight Toolkit</a>’s TransitioningContentControl (which Jesse Liberty has a <a href="http://silverlight.net/blogs/jesseliberty/archive/2009/04/29/animated-visual-state-transitions-with-the-transitioning-content-control.aspx">great blog post on</a>), I think we can get the desired effect!</p>
<p>Let’s begin by taking a peek at the ControlTemplate for the Frame control:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">ControlTemplate </span><span style="color: red">TargetType</span><span style="color: blue">=&quot;navigation:Frame&quot;&gt;
    &lt;</span><span style="color: #a31515">Border </span><span style="color: red">HorizontalAlignment</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">HorizontalContentAlignment</span><span style="color: blue">}&quot;
            </span><span style="color: red">VerticalAlignment</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">VerticalContentAlignment</span><span style="color: blue">}&quot;
            </span><span style="color: red">Background</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">Background</span><span style="color: blue">}&quot;
            </span><span style="color: red">BorderBrush</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">BorderBrush</span><span style="color: blue">}&quot;
            </span><span style="color: red">BorderThickness</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">BorderThickness</span><span style="color: blue">}&quot;&gt;
        &lt;</span><span style="color: #a31515">ContentPresenter </span><span style="color: red">Cursor</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">Cursor</span><span style="color: blue">}&quot;
                          </span><span style="color: red">HorizontalAlignment</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">HorizontalContentAlignment</span><span style="color: blue">}&quot;
                          </span><span style="color: red">Margin</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">Padding</span><span style="color: blue">}&quot;
                          </span><span style="color: red">VerticalAlignment</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">VerticalContentAlignment</span><span style="color: blue">}&quot;
                          </span><span style="color: red">Content</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">Content</span><span style="color: blue">}&quot;/&gt;
    &lt;/</span><span style="color: #a31515">Border</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">ControlTemplate</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>As you can see, there’s very little to it: a Border and a ContentPresenter – with all the appropriate TemplateBindings.</p>
<p>All we have to do to get transitions on the Frame control is replace that ContentPresenter with the TransitioningContentControl:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">ControlTemplate </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Key</span><span style="color: blue">=&quot;TransitioningFrame&quot; </span><span style="color: red">TargetType</span><span style="color: blue">=&quot;navigation:Frame&quot;&gt;
    &lt;</span><span style="color: #a31515">Border </span><span style="color: red">Background</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">Background</span><span style="color: blue">}&quot;
            </span><span style="color: red">BorderBrush</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">BorderBrush</span><span style="color: blue">}&quot;
            </span><span style="color: red">BorderThickness</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">BorderThickness</span><span style="color: blue">}&quot;
            </span><span style="color: red">HorizontalAlignment</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">HorizontalContentAlignment</span><span style="color: blue">}&quot;
            </span><span style="color: red">VerticalAlignment</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">VerticalContentAlignment</span><span style="color: blue">}&quot;&gt;
        &lt;</span><span style="color: #a31515">toolkit</span><span style="color: blue">:</span><span style="color: #a31515">TransitioningContentControl </span><span style="color: red">Content</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">Content</span><span style="color: blue">}&quot;
                                             </span><span style="color: red">Cursor</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">Cursor</span><span style="color: blue">}&quot;
                                             </span><span style="color: red">Margin</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">Padding</span><span style="color: blue">}&quot;
                                             </span><span style="color: red">HorizontalAlignment</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">HorizontalContentAlignment</span><span style="color: blue">}&quot;
                                             </span><span style="color: red">VerticalAlignment</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">VerticalContentAlignment</span><span style="color: blue">}&quot;
                                             </span><span style="color: red">HorizontalContentAlignment</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">HorizontalContentAlignment</span><span style="color: blue">}&quot;
                                             </span><span style="color: red">VerticalContentAlignment</span><span style="color: blue">=&quot;{</span><span style="color: #a31515">TemplateBinding </span><span style="color: red">VerticalContentAlignment</span><span style="color: blue">}&quot;
                                             </span><span style="color: red"><strong><u><em>Transition</em></u></strong></span><span style="color: blue"><strong><u><em>=&quot;&lt;Transition Name&gt;&quot;</em></u></strong> /&gt;
    &lt;/</span><span style="color: #a31515">Border</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">ControlTemplate</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>The “toolkit:” xml namespace uses the following definition (since you can find the TransitioningContentControl in the System.Windows.Controls namespace and the System.Windows.Controls.Layout.Toolkit assembly): xmlns:toolkit=&quot;clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit&quot;</p>
<p>To change the type of transition the Frame will use, just change the value of the Transition property on the TransitioningContentControl.</p>
<p>There’s not much more to it!&#160; Short, sweet, and to the point <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Check out the live sample and source if you’re curious:</p>
<ul>
<li><a href="http://www.davidpoll.com/Samples/TransitioningNavigation/TestPage.html">Sample</a> </li>
<li><a href="http://www.davidpoll.com/Download/TransitioningNavigation.zip">Sample Source</a> </li>
</ul>
<p>&#160;</p>
<p><strong><font size="4">Caveats and Questions</font></strong></p>
<p>I know you’d be disappointed if I really left it at that, so here’s the one caveat I’ve observed with this technique:</p>
<p>My <a href="http://www.davidpoll.com/?p=92">dynamically-loaded libraries with navigation workaround</a> will cause a few problems with this technique, since it sets the Frame’s Content property twice (once to load the DynamicPageShim, the other to load the DynamicPage itself).&#160; The result is that you will see the Frame transition to a blank page and then to the DynamicPage with your content.&#160; So here’s the question: how important is this transitioning behavior to you?&#160; There are two options for how I proceed here, neither of which are truly ideal:</p>
<ol>
<li>Leave DynamicPage and DynamicPageShim as-is and live with the slight wonkiness during transitions. </li>
<li>Make DynamicPageShim avoid changing the content of the Frame twice (making transitions work just fine <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ).&#160; This will mean that you won’t be able to use the DynamicPage<strong><em>exactly</em></strong> as you would the standard Page (e.g. binding to &quot;Frame.Content.MyCustomPropertyOnMyPage” won’t be possible… instead you’d have to bind to “Frame.Content.<strong><em>Content</em></strong>.MyCustomPropertyOnMyPage”). </li>
</ol>
<p>Neither of these options significantly hampers functionality – just impacts either user experience or developer experience, but I’d love to hear your thoughts!&#160; Do you prefer option 1 or option 2?</p>
<p>In the meantime, I’m working on some fun little utilities that will make dynamically loading assemblies with navigation much simpler and more declarative, and am looking forward to blogging it when it’s ready!</p>
<p>&#160;</p>
<p><strong><font size="4">Update: Credit where credit is due</font></strong></p>
<p>About 10 minutes after I posted this, I came across someone (<a href="http://firstfloorsoftware.com/blog/">Koen Zwikstra</a>) who posted almost the exact same thing before me, and I want to make sure he gets fair mention for getting there before me <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>You can find his post here: <a title="http://firstfloorsoftware.com/blog/animated-page-navigation-in-sl3/" href="http://firstfloorsoftware.com/blog/animated-page-navigation-in-sl3/">http://firstfloorsoftware.com/blog/animated-page-navigation-in-sl3/</a></p>
<p>Sorry for duplicating!&#160; Great stuff!</p>
<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.davidpoll.com/2009/07/19/silverlight-3-navigation-adding-transitions-to-the-frame-control/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Silverlight 3 Navigation: Navigating to Pages in dynamically-loaded assemblies</title>
		<link>http://www.davidpoll.com/2009/07/14/silverlight-3-navigation-navigating-to-pages-in-dynamically-loaded-assemblies/</link>
		<comments>http://www.davidpoll.com/2009/07/14/silverlight-3-navigation-navigating-to-pages-in-dynamically-loaded-assemblies/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 06:47:11 +0000</pubDate>
		<dc:creator>david.poll</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Navigation]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Silverlight 3]]></category>

		<guid isPermaLink="false">http://www.davidpoll.com/?p=92</guid>
		<description><![CDATA[In my last post on the new navigation feature in Silverlight, I explored how you can navigate to pages in assemblies/projects referenced by your main application.&#160; Almost immediately, a number of you asked how you can navigate to pages in assemblies that have been dynamically loaded, allowing you to delay downloading certain pieces of your [...]]]></description>
			<content:encoded><![CDATA[<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_start --><p>In my <a href="http://www.davidpoll.com/?p=88">last post on the new navigation feature in Silverlight</a>, I explored how you can navigate to pages in assemblies/projects referenced by your main application.&#160; Almost immediately, a number of you asked how you can navigate to pages in assemblies that have been dynamically loaded, allowing you to delay downloading certain pieces of your application until users request them.&#160; This allows you to reduce the initial size (and thereby load/download time) of your application to something more appropriate for your users and avoid using bandwidth to download components to users’ machines that they may never actually user/encounter.</p>
<p>Out of the box, Silverlight 3’s navigation feature only allows navigating to Pages in assemblies referenced by your application project and packaged in your XAP.&#160; There are a number of technical reasons behind this that I know we’d like to explore and hopefully address in future versions, but I won’t go into the details here.&#160; There is, however, one exception to this rule that prevents us from navigating to Pages in dynamically-loaded assemblies: you <strong><em>can</em></strong> load Pages with no code behind that live in such assemblies.</p>
<p>After a few months of thinking about this problem in the back of my mind, it finally clicked for me: this exception is the way in!&#160; All of the other workarounds I was able to think of required Pages located in the XAP that would load their contents dynamically and didn’t really take advantage of the Navigation feature at all.</p>
<p>Anyway, I think I finally found a reasonably good workaround, and while it’s a little hacky-er than I would’ve liked, it doesn’t fundamentally change the feel of using Silverlight navigation.&#160; Here’s the gist of my strategy:</p>
<ul>
<li>Load an assembly containing a Page dynamically </li>
<li>Include in this assembly a “shim” Page with no code behind.&#160; In its XAML, reference the <em>real</em> page <strong>with</strong> code behind, and forward any navigation-related information (events, title, query strings, etc.) to that Page </li>
<li>When that page is navigated to, replace the Frame’s content with the <em>real</em> page. </li>
<li>From the application, navigate to the “shim” page in the dynamically-loaded assembly </li>
</ul>
<p>Ok, I know that sounds a little roundabout, but I think I’ve made it pretty easy to accomplish for a developer now.&#160; More importantly – it works!</p>
<p>Let me go into a little more detail…</p>
<p><strong><span style="font-size: medium">The Library</span></strong></p>
<p>I’ve created a tiny little assembly that I’ve called “DynamicNavigation”.&#160; It contains two classes, both of which are made for use in XAML:</p>
<ul>
<li><strong>DynamicPage</strong>: A descendant of the Page class that allows the Shim to communicate with it.&#160; If I did my job correctly, for 99% of cases, you can navigate directly to this page (rather than its Shim) if you haven’t dynamically loaded the assembly.&#160; There shouldn’t really be any new public interface (except for some “new” properties that hide the original Page properties, since they aren’t virtual). </li>
<li><strong>DynamicPageShim</strong>:&#160; Another descendant of the Page class, meant to be used in XAML with no code behind.&#160; This class will forward any navigation events, etc., to the DynamicPage it takes as its content.&#160; The goal here was to minimize the XAML so that the additional size due to these files is small.&#160; There may be further optimizations I can do, but it’s getting pretty close <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </li>
</ul>
<p><strong><span style="font-size: medium">The Developer Experience</span></strong></p>
<p>Ok, that’s all great, but what do I have to do to use it?</p>
<p>Well, instead of 2 files (&lt;PageName&gt;.xaml and &lt;PageName&gt;.xaml.cs/vb), creating a Page now takes 3 files:</p>
<ul>
<li><em>&lt;PageName&gt;.dyn.xaml:</em> </li>
</ul>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">dyn</span><span style="color: blue">:</span><span style="color: #a31515">DynamicPageShim </span><span style="color: red">xmlns</span><span style="color: blue">=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
           </span><span style="color: red">xmlns</span><span style="color: blue">:</span><span style="color: red">dyn</span><span style="color: blue">=&quot;clr-namespace:DynamicNavigation;assembly=DynamicNavigation&quot;
           </span><span style="color: red">xmlns</span><span style="color: blue">:</span><span style="color: red">my</span><span style="color: blue">=&quot;clr-namespace:DynamicallyLoadedLibrary;<span style="text-decoration: underline"><strong><em>assembly=DynamicallyLoadedLibrary</em></strong></span>&quot;&gt;
    &lt;</span><span style="color: #a31515">my</span><span style="color: blue">:</span><span style="color: #a31515"><strong><em><span style="text-decoration: underline">PageName</span></em></strong> </span><span style="color: blue">/&gt;
&lt;/</span><span style="color: #a31515">dyn</span><span style="color: blue">:</span><span style="color: #a31515">DynamicPageShim</span><span style="color: blue">&gt;</span></pre>
<p>I’ve underlined two important lines here.&#160; First, “assembly=DynamicallyLoadedLibrary” – normally, this would be unnecessary in an xmlns definition, since I can refer to the library in which the XAML file exists without the “assembly=” syntax.&#160; For the same technical reasons that we normally can’t load a Page in a dynamically-loaded assembly, this name needs to be fully specified, since it allows the XAML loader to find the dynamically-loaded assembly in which your DynamicPage resides.&#160; Next, you can see that this Shim takes an instance of the DynamicPage as its content.&#160; This allows it to forward navigation-related information to the Page and ensure that the Frame has the correct content.</p>
<ul>
<li><em>&lt;PageName&gt;.xaml</em> </li>
</ul>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">dyn</span><span style="color: blue">:</span><span style="color: #a31515">DynamicPage </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Class</span><span style="color: blue">=&quot;DynamicallyLoadedLibrary.CSDynamicPage&quot;
           </span><span style="color: red">xmlns</span><span style="color: blue">=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
           </span><span style="color: red">xmlns</span><span style="color: blue">:</span><span style="color: red">x</span><span style="color: blue">=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
           </span><span style="color: red">xmlns</span><span style="color: blue">:</span><span style="color: red">d</span><span style="color: blue">=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
           </span><span style="color: red">xmlns</span><span style="color: blue">:</span><span style="color: red">mc</span><span style="color: blue">=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
           </span><span style="color: red">xmlns</span><span style="color: blue">:</span><span style="color: red">dyn</span><span style="color: blue">=&quot;clr-namespace:DynamicNavigation;assembly=DynamicNavigation&quot;
           </span><span style="color: red">xmlns</span><span style="color: blue">:</span><span style="color: red">navigation</span><span style="color: blue">=&quot;clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation&quot;
           </span><span style="color: red">mc</span><span style="color: blue">:</span><span style="color: red">Ignorable</span><span style="color: blue">=&quot;d&quot;
           </span><span style="color: red">d</span><span style="color: blue">:</span><span style="color: red">DesignWidth</span><span style="color: blue">=&quot;640&quot; </span><span style="color: red">d</span><span style="color: blue">:</span><span style="color: red">DesignHeight</span><span style="color: blue">=&quot;480&quot;
           </span><span style="color: red">Title</span><span style="color: blue">=&quot;Page Title&quot;&gt;
    &lt;</span><span style="color: #a31515">Grid </span><span style="color: red">x</span><span style="color: blue">:</span><span style="color: red">Name</span><span style="color: blue">=&quot;LayoutRoot&quot;&gt;</span>

<span style="color: blue">       ...</span>

<span style="color: blue">    &lt;/</span><span style="color: #a31515">Grid</span><span style="color: blue">&gt;
&lt;/</span><span style="color: #a31515">dyn</span><span style="color: blue">:</span><span style="color: #a31515">DynamicPage</span><span style="color: blue">&gt;
</span></pre>
<p>As you can see, there’s really nothing special about the DynamicPage except that the open/close tags are of type DynamicPage rather than Page.&#160; Gotta love it!</p>
<ul>
<li><em>&lt;PageName&gt;.xaml.cs/vb</em> </li>
</ul>
<p>I won’t show an example here, but there’s really nothing special about this.&#160; You’ll develop exactly as though the DynamicPage were a real Page.&#160; The only thing to watch out for: please don’t cast the DynamicPage to a Page, since this will cause it to refer to hidden properties that may not be set.&#160; Again, for 99% of cases, this is probably not an issue, but it bears a little bit of consideration.</p>
<p>The last piece of the puzzle is actually navigating to the page.&#160; Well, it’s pretty straightforward: navigate just as we did in <a href="http://www.davidpoll.com/?p=88">my other post</a> (using “;component” pack URI syntax).&#160; The only difference: <em>instead of navigating to &lt;PageName&gt;.xaml, you’ll navigate to &lt;PageName&gt;.dyn.xaml</em>.</p>
<p>And that’s it!&#160; The rest should just work!</p>
<p>So, without further ado, I’ve got some tools for you!</p>
<p><strong><span style="font-size: medium">The Goods</span></strong></p>
<ul>
<li><a href="http://www.davidpoll.com/Download/DynamicNavigation.zip">DynamicNavigation Download</a> </li>
</ul>
<p>The download above is a zip containing 3 things:</p>
<ol>
<li>DynamicNavigation.dll – an assembly you should reference in both your application project (and include in your xap) as well as any assemblies you wish to dynamically load (so that you can include the XAML files above) </li>
<li>DynamicPageCS.zip – this is a Visual Studio item template that will help get you started.&#160; Drop this zip (without extracting) in <em>“&lt;My Documents&gt;\Visual Studio 2008\Templates\Item Templates\Visual C#”</em>.&#160; Now, if you open Visual Studio and a C# Silverlight 3 project, right-click the project (in the solution explorer) and choose “Add new…”.&#160; Select “Silverlight Dynamic Page” and choose a name for your page.&#160; The item template will create the 3 files for you.&#160; Open up “&lt;PageName&gt;.xaml” and start editing! </li>
<li>DynamicPageVB.zip – I didn’t forget about you VB guys!&#160; Follow the same instructions above (but placing the item template in the VB folder instead of the C# one), and you should be set to go! </li>
</ol>
<p>I’m sure there are some bugs and issues with what I did (for example, the item templates don’t add a reference to DynamicNavigation.dll to your project yet… I hope to fix this once I figure out how!).&#160; Let me know if something’s causing you problems, and I’ll see if I can work it out in my (not so) copious free time <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong><span style="font-size: medium">The Sample</span></strong></p>
<p>You know me – I can’t leave you without a live sample of this thing in action!&#160; Take a look here (for your viewing pleasure):</p>
<ul>
<li><a href="http://www.davidpoll.com/Samples/DynamicNavigationApplication/DynamicNavigationApplicationTestPage.html">Sample</a> </li>
<li><a href="http://www.davidpoll.com/Samples/Download/DynamicNavigationSample.zip">Sample Source</a> </li>
</ul>
<p>Enjoy!&#160; You may even find a cameo from a previous post in there!</p>
<p><strong><span style="font-size: medium">The Tips</span></strong></p>
<p>When using my DynamicNavigation tools, there are a few things you should keep in mind.&#160; Hopefully this list will get smaller going forward, but in the meantime, these are some things to remember:</p>
<ul>
<li>It’s still up to you to load the assemblies dynamically into your AppDomain before attempting to navigate to them.&#160; A super-simple example of how to do this can be found in the code-behind of my MainPage.xaml.&#160; You can also use tools like <a href="http://blogs.msdn.com/dphill/archive/tags/Prism/default.aspx">Prism</a> to accomplish something similar.&#160; There are definitely some tricks that would make this feel more on-demand than what I’ve done in the sample, but that’s a topic for a future post! <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </li>
<li>Along those lines, please make sure any assemblies your dynamically-loaded assembly is dependent upon are loaded before trying to navigate.&#160; I don’t do anything to try to resolve those dependencies. </li>
<li>Try to avoid casting your DynamicPage to its parent type – Page.&#160; If you do, you’ll find some properties aren’t set to your desired values (such as Title, NavigationCacheMode, etc.). </li>
<li>My libraries should replace Frame’s Content with the intended page, so feel free to bind into Frame.Content just as you would otherwise.&#160; You may find that Frame.Content does change twice during a navigation rather than just once, but otherwise, you should get the same events/virtual methods called/etc. on your Page. </li>
<li>Expect Caching and Title to still be honored properly on your page! </li>
<li>Once you’ve created your &lt;PageName&gt;.dyn.xaml file, you should rarely, if ever, need to modify it.&#160; It’s just a shim, and any other work you’d like to do should be possible directly through the DynamicPage files (.xaml and .xaml.cs/vb) </li>
</ul>
<p>I tried to keep the library as small as possible.&#160; Anything I build on top of this, I intend to put in a separate library, so that you’re not forced to take additional overhead for the simplest of cases, where you’ve already done your dynamic loading and just want to navigate to pages in those libraries.</p>
<p><strong><span style="font-size: medium">The Conclusion</span></strong></p>
<p>My hope is that this will get you started down the road to navigating to dynamically-loaded assemblies.&#160; I know it’s a bit obtuse, and still harder to do than it ought to be, but what I’d like to do going forward is take this development and create an SL3 library that will make it really simple to download assemblies from your server on-demand during navigation (and perhaps devise some other nifty features).</p>
<p>Please, let me know what you think.&#160; Should I spend more time on these things?&#160; How valuable is using navigation in this way to you?&#160; What kinds of scenarios would you still like to see enabled?</p>
<p>If I’ve confused the heck out of you, I sincerely apologize.&#160; I know I found myself struggling to describe this adequately, so please, ask questions!&#160; I’m happy to share my thoughts/experiences.</p>
<p>Comment away!</p>
<p><strong><em>P.S.</em></strong> I’m finally on Twitter (at least partially to my dismay <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ).&#160; You can find me at @depoll</p>
<p>&#160;</p>
<p><strong><em>Update: </em></strong><a href="http://anoriginalidea.wordpress.com/">Julian Biddle</a> has posted a wholly different strategy that would allow you to divide your Silverlight application across multiple XAPs on his blog: <a title="http://anoriginalidea.wordpress.com/2009/07/22/how-to-build-huge-dynamic-cross-platform-silverlight-business-applications/" href="http://anoriginalidea.wordpress.com/2009/07/22/how-to-build-huge-dynamic-cross-platform-silverlight-business-applications/">http://anoriginalidea.wordpress.com/2009/07/22/how-to-build-huge-dynamic-cross-platform-silverlight-business-applications/</a>.&#160; Take a look – it’s an interesting read/approach <img src='http://www.davidpoll.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<!-- Advanced AdSense by Jim Gaudet --><!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.davidpoll.com/2009/07/14/silverlight-3-navigation-navigating-to-pages-in-dynamically-loaded-assemblies/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
	</channel>
</rss>

