Illustrates a complete Access-based site-map provider.
Example
The following code example demonstrates how you can extend the
Visual BasicВ | ![]() |
---|---|
Imports System Imports System.Collections Imports System.Collections.Specialized Imports System.Data Imports System.Data.OleDb Imports System.Security.Permissions Imports System.Web Namespace Samples.AspNet.VB.Controls ' An extremely simple AccessSiteMapProvider that only supports a ' site map node hierarchy one level deep. <AspNetHostingPermission(SecurityAction.Demand, Level:=AspNetHostingPermissionLevel.Minimal)> _ Public Class AccessSiteMapProvider Inherits StaticSiteMapProvider Private aRootNode As SiteMapNode = Nothing Private accessConnection As OleDbConnection = Nothing ' This string is case sensitive. Private AccessConnectionStringName As String = "accessSiteMapConnectionString" ' Implement a default constructor. Public Sub New() End Sub 'New ' Some basic state to help track the initialization state of the provider. Private initialized As Boolean = False Public Overridable ReadOnly Property IsInitialized() As Boolean Get Return initialized End Get End Property ' Return the root node of the current site map. Public Overrides ReadOnly Property RootNode() As SiteMapNode Get Return BuildSiteMap() End Get End Property Protected Overrides Function GetRootNodeCore() As SiteMapNode Return RootNode End Function ' Initialize is used to initialize the properties and any state that the ' AccessProvider holds, but is not used to build the site map. ' The site map is built when the BuildSiteMap method is called. Public Overrides Sub Initialize(ByVal name As String, ByVal attributes As NameValueCollection) If IsInitialized Then Return End If MyBase.Initialize(name, attributes) ' Create and test the connection to the Microsoft Access database. ' Retrieve the Value of the Access connection string from the ' attributes NameValueCollection. Dim connectionString As String = attributes(AccessConnectionStringName) If Nothing = connectionString OrElse connectionString.Length = 0 Then Throw New Exception("The connection string was not found.") Else accessConnection = New OleDbConnection(connectionString) End If initialized = True End Sub 'Initialize ' SiteMapProvider and StaticSiteMapProvider methods that this derived class must override. ' ' Clean up any collections or other state that an instance of this may hold. Protected Overrides Sub Clear() SyncLock Me aRootNode = Nothing MyBase.Clear() End SyncLock End Sub 'Clear ' Build an in-memory representation from persistent ' storage, and return the root node of the site map. Public Overrides Function BuildSiteMap() As SiteMapNode ' Since the SiteMap class is static, make sure that it is ' not modified while the site map is built. SyncLock Me ' If there is no initialization, this method is being ' called out of order. If Not IsInitialized Then Throw New Exception("BuildSiteMap called incorrectly.") End If ' If there is no root node, then there is no site map. If aRootNode Is Nothing Then ' Start with a clean slate Clear() ' Select the root node of the site map from Microsoft Access. Dim rootNodeId As Integer = -1 If accessConnection.State = ConnectionState.Closed Then accessConnection.Open() End If Dim rootNodeCommand As New OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid IS NULL", accessConnection) Dim rootNodeReader As OleDbDataReader = rootNodeCommand.ExecuteReader() If rootNodeReader.HasRows Then rootNodeReader.Read() rootNodeId = rootNodeReader.GetInt32(0) ' Create a SiteMapNode that references the current StaticSiteMapProvider. aRootNode = New SiteMapNode(Me, rootNodeId.ToString(), rootNodeReader.GetString(1), rootNodeReader.GetString(2)) Else Return Nothing End If rootNodeReader.Close() ' Select the child nodes of the root node. Dim childNodesCommand As New OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid = ?", accessConnection) Dim rootParam As New OleDbParameter("parentid", OleDbType.Integer) rootParam.Value = rootNodeId childNodesCommand.Parameters.Add(rootParam) Dim childNodesReader As OleDbDataReader = childNodesCommand.ExecuteReader() If childNodesReader.HasRows Then Dim childNode As SiteMapNode = Nothing While childNodesReader.Read() childNode = New SiteMapNode(Me, _ childNodesReader.GetInt32(0).ToString(), _ childNodesReader.GetString(1), _ childNodesReader.GetString(2)) ' Use the SiteMapNode AddNode method to add ' the SiteMapNode to the ChildNodes collection. AddNode(childNode, aRootNode) End While End If childNodesReader.Close() accessConnection.Close() End If Return aRootNode End SyncLock End Function 'BuildSiteMap End Class 'AccessSiteMapProvider End Namespace |
C#В | ![]() |
---|---|
namespace Samples.AspNet.CS.Controls { using System; using System.Collections; using System.Collections.Specialized; using System.Data; using System.Data.OleDb; using System.Security.Permissions; using System.Web; /// An extremely simple AccessSiteMapProvider that only supports a /// site map node hierarchy 1 level deep. [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Minimal)] public class AccessSiteMapProvider : StaticSiteMapProvider { private SiteMapNode rootNode = null; private OleDbConnection accessConnection = null; // This string is case sensitive. private string AccessConnectionStringName = "accessSiteMapConnectionString"; // Implement a default constructor. public AccessSiteMapProvider () { } // Some basic state to help track the initialization state of the provider. private bool initialized = false; public virtual bool IsInitialized { get { return initialized; } } // Return the root node of the current site map. public override SiteMapNode RootNode { get { SiteMapNode temp = null; temp = BuildSiteMap(); return temp; } } protected override SiteMapNode GetRootNodeCore() { return RootNode; } // Initialize is used to initialize the properties and any state that the // AccessProvider holds, but is not used to build the site map. // The site map is built when the BuildSiteMap method is called. public override void Initialize(string name, NameValueCollection attributes) { if (IsInitialized) return; base.Initialize(name, attributes); // Create and test the connection to the Microsoft Access database. // Retrieve the Value of the Access connection string from the // attributes NameValueCollection. string connectionString = attributes[AccessConnectionStringName]; if (null == connectionString || connectionString.Length == 0) throw new Exception ("The connection string was not found."); else accessConnection = new OleDbConnection(connectionString); initialized = true; } /// /// SiteMapProvider and StaticSiteMapProvider methods that this derived class must override. /// // Clean up any collections or other state that an instance of this may hold. protected override void Clear() { lock (this) { rootNode = null; base.Clear(); } } // Build an in-memory representation from persistent // storage, and return the root node of the site map. public override SiteMapNode BuildSiteMap() { // Since the SiteMap class is static, make sure that it is // not modified while the site map is built. lock(this) { // If there is no initialization, this method is being // called out of order. if (! IsInitialized) { throw new Exception("BuildSiteMap called incorrectly."); } // If there is no root node, then there is no site map. if (null == rootNode) { // Start with a clean slate Clear(); // Select the root node of the site map from Microsoft Access. int rootNodeId = -1; if (accessConnection.State == ConnectionState.Closed) accessConnection.Open(); OleDbCommand rootNodeCommand = new OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid IS NULL", accessConnection); OleDbDataReader rootNodeReader = rootNodeCommand.ExecuteReader(); if(rootNodeReader.HasRows) { rootNodeReader.Read(); rootNodeId = rootNodeReader.GetInt32(0); // Create a SiteMapNode that references the current StaticSiteMapProvider. rootNode = new SiteMapNode(this, rootNodeId.ToString(), rootNodeReader.GetString(1), rootNodeReader.GetString(2)); } else return null; rootNodeReader.Close(); // Select the child nodes of the root node. OleDbCommand childNodesCommand = new OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid = ?", accessConnection); OleDbParameter rootParam = new OleDbParameter("parentid", OleDbType.Integer); rootParam.Value = rootNodeId; childNodesCommand.Parameters.Add(rootParam); OleDbDataReader childNodesReader = childNodesCommand.ExecuteReader(); if (childNodesReader.HasRows) { SiteMapNode childNode = null; while(childNodesReader.Read()) { childNode = new SiteMapNode(this, childNodesReader.GetInt32(0).ToString(), childNodesReader.GetString(1), childNodesReader.GetString(2)); // Use the SiteMapNode AddNode method to add // the SiteMapNode to the ChildNodes collection. AddNode(childNode, rootNode); } } childNodesReader.Close(); accessConnection.Close(); } return rootNode; } } } } |
C++В | ![]() |
---|---|
#using <System.Data.dll> #using <System.Transactions.dll> #using <System.EnterpriseServices.dll> #using <System.dll> #using <System.Web.dll> #using <System.Configuration.dll> using namespace System; using namespace System::Collections; using namespace System::Collections::Specialized; using namespace System::Configuration; using namespace System::Data; using namespace System::Data::OleDb; using namespace System::Security::Permissions; using namespace System::Web; /// An extremely simple AccessSiteMapProvider that only supports a /// site map node hierarchy 1 level deep. [AspNetHostingPermission(SecurityAction::Demand,Level=AspNetHostingPermissionLevel::Minimal)] public ref class AccessSiteMapProvider: public StaticSiteMapProvider { private: SiteMapNode ^ rootNode; OleDbConnection^ accessConnection; // This string is case sensitive. String^ AccessConnectionStringName; public: // Implement a default constructor. AccessSiteMapProvider() { initialized = false; AccessConnectionStringName = "accessSiteMapConnectionString"; } private: // Some basic state to help track the initialization state of the provider. bool initialized; public: property bool IsInitialized { virtual bool get() { return initialized; } } property SiteMapNode ^ RootNode { // Return the root node of the current site map. virtual SiteMapNode ^ get() override { SiteMapNode ^ temp = nullptr; temp = BuildSiteMap(); return temp; } } protected: virtual SiteMapNode ^ GetRootNodeCore() override { return RootNode; } public: // Initialize is used to initialize the properties and any state that the // AccessProvider holds, but is not used to build the site map. // The site map is built when the BuildSiteMap method is called. virtual void Initialize( String^ name, NameValueCollection^ attributes ) override { if ( IsInitialized ) return; StaticSiteMapProvider::Initialize( name, attributes ); // Create and test the connection to the Microsoft Access database. // Retrieve the Value of the Access connection string from the // attributes NameValueCollection. String^ connectionString = attributes[ AccessConnectionStringName ]; if ( nullptr == connectionString || connectionString->Length == 0 ) throw gcnew Exception( "The connection string was not found." ); else accessConnection = gcnew OleDbConnection( connectionString ); initialized = true; } protected: /// /// SiteMapProvider and StaticSiteMapProvider methods that this derived class must override. /// // Clean up any collections or other state that an instance of this may hold. virtual void Clear() override { System::Threading::Monitor::Enter( this ); try { rootNode = nullptr; StaticSiteMapProvider::Clear(); } finally { System::Threading::Monitor::Exit( this ); } } public: // Build an in-memory representation from persistent // storage, and return the root node of the site map. virtual SiteMapNode ^ BuildSiteMap() override { // Since the SiteMap class is static, make sure that it is // not modified while the site map is built. System::Threading::Monitor::Enter( this ); try { // If there is no initialization, this method is being // called out of order. if ( !IsInitialized ) { throw gcnew Exception( "BuildSiteMap called incorrectly." ); } // If there is no root node, then there is no site map. if ( nullptr == rootNode ) { // Start with a clean slate Clear(); // Select the root node of the site map from Microsoft Access. int rootNodeId = -1; if ( accessConnection->State == ConnectionState::Closed ) accessConnection->Open(); OleDbCommand^ rootNodeCommand = gcnew OleDbCommand ("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid IS NULL", accessConnection); OleDbDataReader^ rootNodeReader = rootNodeCommand->ExecuteReader(); if ( rootNodeReader->HasRows ) { rootNodeReader->Read(); rootNodeId = rootNodeReader->GetInt32( 0 ); // Create a SiteMapNode that references the current StaticSiteMapProvider. rootNode = gcnew SiteMapNode(this, rootNodeId.ToString(), rootNodeReader->GetString( 1 ),rootNodeReader->GetString( 2 )); } else return nullptr; rootNodeReader->Close(); // Select the child nodes of the root node. OleDbCommand^ childNodesCommand = gcnew OleDbCommand ("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid = ?", accessConnection); OleDbParameter^ rootParam = gcnew OleDbParameter( "parentid", OleDbType::Integer); rootParam->Value = rootNodeId; childNodesCommand->Parameters->Add( rootParam ); OleDbDataReader^ childNodesReader = childNodesCommand->ExecuteReader(); if ( childNodesReader->HasRows ) { SiteMapNode ^ childNode = nullptr; while ( childNodesReader->Read() ) { childNode = gcnew SiteMapNode( this, System::Convert::ToString(childNodesReader->GetInt32( 0 )), childNodesReader->GetString( 1 ), childNodesReader->GetString( 2 ) ); // Use the SiteMapNode AddNode method to add // the SiteMapNode to the ChildNodes collection. AddNode( childNode, rootNode ); } } childNodesReader->Close(); accessConnection->Close(); } return rootNode; } finally { System::Threading::Monitor::Exit( this ); } } }; |
To create the Access table that is used by the previous code example as the site-map data store, issue the following data-definition query in a new or existing Access database, and then save the Access database with the file name Sitemap.mdb.
В | ![]() |
---|---|
CREATE TABLE SiteMap ( URL Text (255) UNIQUE, NAME Text (255) NOT NULL, PARENTNODEID Int32, CONSTRAINT NODEID PRIMARY KEY (URL, NAME) ) |
Populate the table with the following kinds of data, listing files that you have in your Web site or files that you can create. The following table shows an example file listing.
NODEID | URL | NAME | PARENTNODEID |
---|---|---|---|
1 |
Default.aspx |
Default |
null (empty cell) |
2 |
Catalog.aspx |
Catalog |
1 |
3 |
Aboutus.aspx |
Contact Us |
1 |
![]() |
---|
Because data sources contain differing SQL syntax, some commands will work with one data source and not with another. As a result, it is recommended that you create a site-map provider that is specific to your data source, even if you are using the .NET Framework Data Provider for ODBC or the .NET Framework Data Provider for OLEВ DB to access your data source (for example, SybaseSiteMapProvider, OracleSiteMapProvider, and so on). |
The AccessSiteMapProvider
class derives from the StaticSiteMapProvider class, and retrieves its information from an Access database using basic SQL queries as well as
Finally, AccessSiteMapProvider
is configured to be the default provider in the Web.config file, as shown in the following code example.
В | ![]() |
---|---|
<configuration> <system.web> <siteMap defaultProvider="AccessSiteMapProvider"> <providers> <add name="AccessSiteMapProvider" type="<type name>" accessSiteMapConnectionString="PROVIDER=MICROSOFT.JET.OLEDB.4.0;DATA SOURCE=<path>\sitemap.mdb "/> </providers> </siteMap> </system.web> </configuration> |
To customize this example, replace <type name>
with the fully qualified name of the class that implements your site-map data provider. For example, in the C# code above, you would replace <type name>
with Samples.AspNet.CS.Controls.AccessSiteMapProvider
. If you compile your site-map data provider code and place it in the Bin directory, the <type name>
string must also include the name of your compiled file without the file name extension. For example, if you compiled the C# code above into a file called Samples.AspNet.dll, you would replace <type name>
with Samples.AspNet.CS.Controls.AccessSiteMapProvider.Samples.AspNet
. Lastly, replace <path>
with the absolute physical path to your site-map database.
![]() |
---|
When you inherit from StaticSiteMapProvider, you must override the following members: |
Robust Programming
If you are extending the StaticSiteMapProvider class, the three most important methods are GetRootNodeCore,
See Also
Reference
Concepts
ASP.NET Site Navigation OverviewSecuring ASP.NET Site Navigation
Securing Data Access