OpenLightGroup Blog


Blogs from

Silverlight, SEO & ASP.Net – Part 3 (Version 1 Setup)

I created a package and posted it to the CodePlex site associated with this series of articles. The package aims to allow you to easily implement the strategy outlined in Part 2 (Solidifying a Strategy) of these posts. This article will discuss how to integrate the code in the package with your existing ASP.Net site to allow links to be mapped between current urls and new Silverlight Deep Links. With the page mappings in place, you can effectively move your entire site to Silverlight while maintaining the links already indexed by the search engines. This also allows users that have not installed Silverlight and search engine bots to continue to use the original ASP.Net site.

A correction is needed for some information in the previous post. Apparently, I was mistaken about needing to require the user to click a link to view the Silverlight version of the site. Google will not mark your site as a “cloaking” site because you automatically redirect the users as long as the content provided is the same on both version of the page. The end result is, users with Silverlight installed will be shown the Silverlight version of the site automatically, while all other requests (from users or search bots) will be displayed the ASP.Net version. After implementing the code provided in the download all you will have to do is ensure that the “Page Mappings” are kept up-to-date. This can be done is several ways which will discuss shortly, but let’s not get ahead of ourselves.

First we need to enable the “Page Mapping” framework in our existing site. I have created a very basic example site to demonstrate the process. The site contains one page that calls a web service to retrieve the content for the page based on a query string.

The site structure looks like this:


Again, this is about as simple as I could make the site and still demonstrate “data driven” content. I thought it would be important that the site use dynamic content to show how the data can be shared between ASP.Net and Silverlight. So the ContentService.asmx simply returns a string that is shown in the body of the ASP.Net page. For example, if you navigate to Default.aspx?page=about the page displays “About message from Webservice.” The Silverlight application will use this same service to provide the content for its pages. I also included a master page (Site.master) and a style sheet (DefaultStyles.css) in the site to mimic a typical ASP.Net site and allow me to demonstrate how to integrate the framework into your existing master page.

Now that you have an idea of the site I will be updating we can jump into the process. Start by downloading and extracting the Silverlight SEO Install package from the CodePlex site. Once extracted you should have a folder that looks something like this:


Be sure and read the README.txt in case parts of this process have changed since the writing of this post!

Now we can begin to migrate the code from this folder into our demo website.

Please note, that before copying the files and folders to your site, be sure you are not going to overwrite any files that already exist. If you find that there is already a file with the same name, you should compare the contents and manually merge the two files. For example, robots.txt contains a Disallow for all user agents to the Silverlight.aspx page. If you already have a robots.txt file in place, simply add this entry to it. Also note that, if you site already contains the Silverlight.js file in another location there is no need to copy to your site.

Since I have verified that I have no conflicting files I will go ahead and drop all of the contents of the download into my site (except the README.txt). Now the demo site structure looks like this:


I will now drop in the SimpleSilverlightExample.xap file for the Silverlight application I will be hosting in this site into a ClientBin folder that I will create on the site. Obviously this process will differ for you depending on if your .xap file already exists etc.

Now that the Silverlight app is located in the site, I will update the Silverlight.aspx page to point to the new xap file. To do this I simply edit the source parameter of the object tag located on this page to look like this:

 <param name="source" value="ClientBin/SimpleSilverlightExample.xap" />

While you are editing this page be sure that the Path to the Silverlight.js file is correct for your site. If the Silverlight.js file is not located in the Scripts folder, you will need to modify the ScriptReference tag inside of the MainScriptManager.

By default it looks like this:

    <asp:ScriptManager runat="server" ID="MainScriptManager">
            <asp:ScriptReference Path="~/Scripts/Silverlight.js" />
            <asp:ScriptReference Assembly="OpenLightGroup.PageMapping" Name="OpenLightGroup.PageMapping.PageMappings.js" />
     <!--End Required—>

The only other change you may want to make on this page is, by default a link back to the ASP.Net version of the site is displayed at the bottom of the page. To hide this link uncomment the “display: none;” line the footer style at the top of the page, like this:

            text-align: center;
            font-size: smaller; 
            /*if you do not want to display a link to the 
            non-silverlight version of the site 
            enable the next line */ 
            display: none;

Now let’s move on to adding the necessary code to your master page to do the automatic redirects. First open the SLSEO.master file from the download and browser through the markup. You will notice a few sections marked as “Required”, such as this:

    <script type="text/javascript">
        //Used to configure the service proxy. 
        // This needs to be in all pages that call the mapping service via javascript.
        var pageMappingServicePath = '<%= Me.ResolveURL(ConfigurationManager.AppSettings("PageMappingServicePath")) %>'; 
    <!-- End Required –> 


Copy each of these sections into your own master page. Be sure to place them in the appropriate areas head, top of the body etc. As with the Silverlight.aspx, please check the path to the Silverlight.js file configured in the MainScriptManager as you copy it to your master page. If you already have a ScriptManager on your master page, you only need to copy the ScriptReferences and the script tag located directly under the ScriptManager on the SLSEO.master page.

    <script type="text/javascript">
            <!--            //
            //The next line automatically redirects
            // to user the Silverlight version of the site
            // if Silverlight is installed 



Once you have merged the two master pages, you will need to add the following AppSettings to your web.config file:

    <!--Required Setting for the XmlPageMappingController-->
    <add key="PageMappingsXmlFilePath" value="~/App_Data/PageMappings.xml"/>
    <!--Required Settings -->
    <add key="PageMappingServicePath" value="~/Services/PageMappingsService.asmx"/>
    <add key="PageMappingsController" value="OpenLightGroup.PageMapping.XmlPageMappingsController, OpenLightGroup.PageMapping, PublicKeyToken=null" />

The PageMappingsController setting configures the service to use the XML based page mappings controller. This controller uses the PageMappingsXmlFilePath setting to locate the XML file that contains the list of page mappings. This is the default data store used to keep the page mappings up-to-date; however, as mentioned before, you can develop your own controller to use a different data store. I will discuss how to build a custom controller class in a future article. For now let’s look at the PageMappings.xml file located in the App_Data folder. This file contains a list of links for the ASP.Net site and the associated Silverlight Deep Links. Since the PageMappingsController is also used to provide the search engine SiteMap, the file contains information for the sitemap as well. The XML for my example site looks like this:

<?xml version="1.0" encoding="utf-8" ?>
	<PageMapping htmlUrl="/SeoTest/"
				 order="1" priority="0.5" changeFrequency="always" lastModified="2009-10-01"/>
	<PageMapping htmlUrl="/SeoTest/Default.aspx"
				 order="2" priority="1.0" changeFrequency="always" lastModified="2009-10-01"/>
	<PageMapping htmlUrl="/SeoTest/Default.aspx?page=Home"
				 order="3" priority="1.0" changeFrequency="always" lastModified="2009-10-01"/>
	<PageMapping htmlUrl="/SeoTest/Default.aspx?page=About"
				 order="4" priority="0.2" changeFrequency="monthly" lastModified="2009-10-01"/>

You will need to add the appropriate entries for the links associated with your site. The priority, changeFrequency, and lastModified attributes are used by the controller to generate the search engine sitemap. The htmlUrl is the link for the ASP.Net site and the silverlightUrl is the Silverlight Deep Link associated with the htmlUrl. The order attribute is used to determine which link to redirect to if there are duplicate urls listed. For example, in my file there are two entries for “/SeoTest/Silverlight.aspx.” In this case, when redirecting the “/SeoTest” mapping would be used since it’s order comes before the “/SeoTest/Default.aspx” mapping.

Once you have added the PageMapping entries to this file setup is complete and the site will begin redirecting to the appropriate link based on the availability of the Silverlight plug-in.

In the previous article I stated the following objectives for this code:

Project Objectives:

  1. Provide a way to associate Silverlight Deep Links to a corresponding HTML version of a page and vice versa.
  2. Allow link mappings to be data driven.
  3. Provide a master page that will handle the redirection to the associated Silverlight link.
    • Master page will also display the “Get Microsoft Silverlight” image link be default. This lets users know there is a Silverlight version of the site and shows them where to download the Silverlight Plug-In.
  4. Provide a Silverlight hosting page that will handle displaying a link to the HTML version of the page to users.
    • Search engines will only be able to see a link to the default html page.
  5. Prevent search engines from indexing the page(s) that host the Silverlight content.
  6. Provide a swappable search engine sitemap handler, that can be used to submit to search engines.
  7. Demonstrate a basic example of how to share data driven content between Silverlight and HTML.
  8. Provide Visual Studio templates for ASP.Net and ASP.Net MVC web sites.

Objectives 1-6 are handled by the setup process we just completed and this article completed number seven. That leaves us with number eight. While working on getting this package together it occurred to me that the value of providing templates was relatively low. So for now I am removing that objective from the list as well as providing support for the MVC framework. Technically speaking, everything in this package should work in the MVC framework if with a slightly different setup process and additional changes to Silverlight.aspx to remove the need for the ScriptManager server control. However, I was more focused on getting out the initial release with support for a typical ASP.Net site than delaying the release any longer to focus on MVC sites. I have created some items in the Issue Tracker for this project to allow you to vote on what features you would like to see most. MVC support is one of them, so if you are interested in using this framework with an MVC site, cast your vote for that feature.

From my perspective the biggest drawback to this framework as it comes out of the box, is the PageMappings.xml file. For large sites with dynamic urls this could be a nightmare to manage. This brings us back to the issue of creating your own PageMappingsController class to better handle the more complex scenarios. I hope to dive into this process in my next article sometime soon. However, for those that cannot wait (and do not mind figuring some things out on their own), here is a brief description to point you in the right direction.

Creating your own controller boils down to inheriting from the OpenLightGroup.PageMappings.BasePageMappingController class and updating the PageMappingsController setting in web.config. The process is really rather simple… but that is all I have time to say for now. Check out the next article for a detailed example. In the meantime, if you have any issues using the framework please post them to the Discussions page on the CodePlex site. Also, don’t forget to vote for the features you would like to see in the next release or add features (or bugs) using the Issue Tracker on the CodePlex site.

I hope you enjoyed this article and find the framework useful. As always please leave your (much appreciated feedback) on the article here.

Comments are closed.
Showing 4 Comments
Avatar  artist website 7 years ago

Nice work.

Avatar  Web Traffic 7 years ago

As always, some sources are more reliable than others and the quality and quantity of information varies widely from one resource to the next. Thanks for sharing this tutorial. I actually learned a lot from it. Good job!

Avatar  Ian T. Lackey 8 years ago

Thanks! :)

Avatar  Michael Washington 8 years ago

Good work!