CHAPTER 23 Using Site Maps DataRow[] results = siteMapTable.Select“ParentId=” + parentNode.Key; foreach DataRow row in results { SiteMapNode node = new SiteMapNodethis, row[“Id”].ToStrin
Trang 1CHAPTER 23 Using Site Maps
DataRow[] results = siteMapTable.Select(“ParentId=” + parentNode.Key);
foreach (DataRow row in results)
{
SiteMapNode node = new SiteMapNode(this, row[“Id”].ToString(), row[“url”].ToString(), row[“title”].ToString(),
row[“description”].ToString());
AddNode(node, parentNode);
BuildSiteMapRecurse(siteMapTable, node);
}
}
}
}
Like the custom Site Map provider that was created in the previous section, the
SqlSiteMapProvider derives from the base StaticSiteMapProvider class The
SqlSiteMapProvider class overrides three methods of the base class: Initialize(),
GetRootNodeCore(), and BuildSiteMap()
The Initialize() method retrieves a database connection string from the web
configura-tion file If a database connecconfigura-tion string cannot be retrieved, the method throws a big,
fat exception
Almost all the work happens in the BuildSiteMap() method This method loads the
contents of the SiteMap database table into an ADO.NET DataTable Next, it recursively
builds the Site Map nodes from the DataTable
There is one special aspect of the code in Listing 23.18 It uses a SQL cache dependency
to automatically rebuild the Site Map when the contents of the SiteMap database table
are changed
To enable SQL cache dependencies for a database, you must configure the database with
either the enableNotifications tool or the aspnet_regsql tool Use the
enableNotifications tool when enabling SQL cache dependencies for a SQL Express
data-base table, and use the aspnet_regsql tool when enabling SQL cache dependencies for the
full version of Microsoft SQL Server
NOTE
To learn more about configuring SQL cache dependencies, see Chapter 29, “Caching
Application Pages and Data.”
To enable SQL cache dependencies for a SQL Express database named SiteMapDB that
contains a table named SiteMap, browse to the folder that contains the SiteMapDB.mdf
file and execute the following command from a Command Prompt:
enableNotifications “SiteMapDB.mdf” “SiteMap”
Trang 2You can configure your website to use the SqlSiteMapProvider class with the Web
config-uration file in Listing 23.19
LISTING 23.19 Web.Config
<?xml version=”1.0”?>
<configuration>
<connectionStrings>
<add
name=”conSiteMap”
connectionString=”Data Source=.\SQLExpress;Integrated
Security=True;AttachDbFileName=|DataDirectory|SiteMapDB.mdf;User Instance=True”/>
</connectionStrings>
<system.web>
<siteMap defaultProvider=”myProvider”>
<providers>
<add
name=”myProvider”
type=”AspNetUnleashed.SqlSiteMapProvider”
connectionStringName=”conSiteMap” />
</providers>
</siteMap>
<caching>
<sqlCacheDependency enabled = “true” pollTime = “5000” >
<databases>
<add name=”SiteMapDB”
connectionStringName=”conSiteMap”
/>
</databases>
</sqlCacheDependency>
</caching>
</system.web>
</configuration>
The configuration file in Listing 23.19 accomplishes several tasks First, it configures the
SqlSiteMapProvider as the default Site Map provider The provider includes a
connectionStringName attribute that points to the connection string for the local SQL
Express database named SiteMapDB
The configuration file also enables SQL cache dependency polling The application is
configured to poll the SiteMapDB database for changes every 5 seconds In other words, if
Trang 3ptg CHAPTER 23 Using Site Maps
FIGURE 23.9 Displaying a Site Map from a Microsoft SQL database
you make a change to the SiteMap database table, the Site Map is updated to reflect the
change within 5 seconds
You can try out the SqlSiteMapProvider by opening the Default.aspx page included in
the SqlSiteMapProviderApp web application on the website that accompanies this book If
you modify the SiteMap database table, the changes are automatically reflected in the Site
Map (see Figure 23.9)
Generating a Google SiteMap File
Google provides a free service, named Google SiteMaps, that you can use to monitor and
improve the way that Google indexes the pages on your website For example, you can
use Google SiteMaps to discover which Google search queries have returned pages from
your website and the ranking of your pages in Google search results You also can use
Google SiteMaps to view any problems that the Google crawler encounters when
index-ing your site
You can sign up for Google SiteMaps by visiting the following URL:
http://www.google.com/webmasters/sitemaps
To use Google SiteMaps, you must provide Google with the URL of a Google SiteMap file
hosted on your website The Google SiteMap file is an XML file that contains a list of
URLs you want Google to index
Trang 4The Google SiteMap XML file has the following format:
<?xml version=”1.0” encoding=”UTF-8”?>
<urlset xmlns=”http://www.google.com/schemas/sitemap/0.84”>
<url>
<loc>http://www.example.com/</loc>
<lastmod>2005-01-01</lastmod>
</url>
<url>
<loc>http://www.example.com/sample.html/</loc>
<lastmod>2006-03-11</lastmod>
</url>
</urlset>
The Google SiteMap file contains a simple list of <url> elements that contain <loc>
elements representing the location of the URL and <lastmod> elements representing the
last modified date of the URL
NOTE
The Google SiteMap file also can contain <changefreq> and <priority> elements
The <changefreq> element indicates how frequently a URL changes, and the
<priority> element represents the priority of a URL relative to other URLs in your
site These elements are optional and are ignored here
You can generate a Google SiteMap file automatically from an ASP.NET SiteMap The HTTP
Handler in Listing 23.20 generates a Google SiteMap that conforms to Google’s
require-ments for a valid SiteMap file
LISTING 23.20 PublicSiteMap.ashx
<%@ WebHandler Language=”C#” Class=”PublicSiteMap” %>
using System;
using System.Web;
using System.Xml;
using System.Text;
using System.IO;
public class PublicSiteMap : IHttpHandler {
private XmlWriter _xmlWriter;
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = “text/xml”;
Trang 5CHAPTER 23 Using Site Maps
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
settings.Indent = true;
_xmlWriter = XmlWriter.Create(context.Response.OutputStream,settings);
_xmlWriter.WriteStartDocument();
_xmlWriter.WriteStartElement(“urlset”,”http://www.google.com/schemas/
➥sitemap/0.84”);
// Add root node
AddUrl(SiteMap.RootNode);
// Add all other nodes
SiteMapNodeCollection nodes = SiteMap.RootNode.GetAllNodes();
foreach (SiteMapNode node in nodes)
AddUrl(node);
_xmlWriter.WriteEndElement();
_xmlWriter.WriteEndDocument();
_xmlWriter.Flush();
}
private void AddUrl(SiteMapNode node)
{
// Skip empty Urls
if (String.IsNullOrEmpty(node.Url))
return;
// Skip remote nodes
if (node.Url.StartsWith(“http”, true, null))
return;
// Open url tag
_xmlWriter.WriteStartElement(“url”);
// Write location
_xmlWriter.WriteStartElement(“loc”);
_xmlWriter.WriteString(GetFullUrl(node.Url));
_xmlWriter.WriteEndElement();
// Write last modified
_xmlWriter.WriteStartElement(“lastmod”);
_xmlWriter.WriteString(GetLastModified(node.Url));
_xmlWriter.WriteEndElement();
// Close url tag
_xmlWriter.WriteEndElement();
}
private string GetFullUrl(string url)
Trang 6{
HttpContext context = HttpContext.Current;
string server =
context.Request.Url.GetComponents(UriComponents.SchemeAndServer,
UriFormat.UriEscaped);
return Combine(server, url);
}
private string Combine(string baseUrl, string url)
{
baseUrl = baseUrl.TrimEnd(new char[] {‘/’});
url = url.TrimStart(new char[] { ‘/’ });
return baseUrl + “/” + url;
}
private string GetLastModified(string url)
{
HttpContext context = HttpContext.Current;
string physicalPath = context.Server.MapPath(url);
return File.GetLastWriteTimeUtc(physicalPath).ToString(“s”) + “Z”;
}
public bool IsReusable {
get {
return true;
}
}
}
The HTTP Handler in Listing 23.20 generates an XML file by iterating through each of the
nodes in an ASP.NET Site Map The XML file is created with the help of the XmlWriter
class This class generates each of the XML tags
NOTE
You can think of an HTTP Handler as a lightweight ASP.NET page You learn about HTTP
Handlers in Chapter 31, “Working with the HTTP Runtime.”
The file in Listing 23.21 contains the XML file returned by the PublicSiteMap.ashx
handler when the Handler is called from the sample application contained on the website
that accompanies this book (The file has been abridged to save space.)
Trang 7CHAPTER 23 Using Site Maps
LISTING 23.21 PublicSiteMap.ashx Results
<?xml version=”1.0” encoding=”utf-8”?>
<urlset xmlns=”http://www.google.com/schemas/sitemap/0.84”>
<url>
<loc>http://localhost:2905/SiteMaps/Default.aspx</loc>
<lastmod>2005-10-30T03:13:58Z</lastmod>
</url>
<url>
<loc>http://localhost:2905/SiteMaps/Products/Default.aspx</loc>
<lastmod>2005-10-28T21:48:04Z</lastmod>
</url>
<url>
<loc>http://localhost:2905/SiteMaps/Services</loc>
<lastmod>2005-10-30T04:31:57Z</lastmod>
</url>
<url>
<loc>http://localhost:2905/SiteMaps/Employees/Default.aspx</loc>
<lastmod>1601-01-01T00:00:00Z</lastmod>
</url>
<url>
<loc>http://localhost:2905/SiteMaps/Products/FirstProduct.aspx</loc>
<lastmod>2005-10-30T03:43:52Z</lastmod>
</url>
</urlset>
When you sign up at the Google SiteMaps website, submit the URL of the
PublicSiteMap.ashx file when you are asked to enter your SiteMap URL The Google
service retrieves your SiteMap from the handler automatically
Summary
In this chapter, you learned how to work with Site Maps The first section discussed the
SiteMapDataSource control You learned how to declaratively represent different sets of
nodes in a Site Map with this control
Next, the SiteMap and SiteMapNode classes were examined You learned how to create new
Site Map nodes dynamically by handling the SiteMapResolve event You also learned how
to programmatically retrieve the current Site Map node in a page
The next section discussed several advanced features of Site Maps You learned how to
display different Site Map nodes to different users depending on their roles You also
learned how to merge SiteMap files located in different subfolders Finally, you learned
how to extend Site Maps with custom attributes
Trang 8We also built two custom Site Map providers We created an AutoSiteMapProvider that
automatically builds a Site Map that reflects the folder and page structure of a website We
also created a SqlSiteMapProvider that stores a Site Map in a Microsoft SQL Server
data-base table
Finally, you learned how to use ASP.NET Site Maps with Google SiteMaps In the final
section of this chapter, you learned how to create a custom HTTP Handler that converts
an ASP.NET Site Map into a Google SiteMap so that you can improve the way that Google
indexes your website’s pages
Trang 9This page intentionally left blank
Trang 10Advanced Navigation .. Remapping URLsUsing the
VirtualPathProvider Class Summary
Websites tend to be organic—they grow and change
over time This can create problems when other
applica-tions link to your application You need some way of
modi-fying your website without breaking all the existing links
to your website
In this chapter, you learn how to remap URLs In other
words, you learn how to serve a different page than the
page a user requests In the first section of the chapter, you
learn how to remap URLs in the web configuration file
Next, you learn how to remap URLs by creating a custom
HTTP module Using a module is useful when you need to
support wildcard matches and other types of pattern
match-ing when remappmatch-ing a URL
Finally, you learn how to use the VirtualPathProvider
class to remap URLs You learn how you can store all your
website pages in a database In the last section of this
chapter, a simple Content Management System (CMS) is
built with the VirtualPathProvider class
All these techniques are different than the techniques that
use the new ASP.NET 4 Routing Engine If your goal is to
provide “permalink” type functionality or specifically map
URLs to pieces of content (rather than aspx pages), these
techniques are for you However, if your goal is to provide a
more SEO-friendly, user-friendly, and possibly REST-friendly
URL pattern for your entire website, you should not use the
techniques in this chapter and instead skip to the chapter
on the URL Routing Engine