Exemplo de Provedor de Mapa do Site do Access
Ilustra um provedor completo de mapa de site baseado em texto.
Exemplo
Descrição
O exemplo de código a seguir demonstra como escrever uma classe que implementa a classe abstrata SiteMapProvider.
Código
Imports System
Imports System.Collections
Imports System.Collections.Specialized
Imports System.Configuration.Provider
Imports System.IO
Imports System.Security.Permissions
Imports System.Web
Namespace Samples.AspNet.VB
<AspNetHostingPermission(SecurityAction.Demand, Level:=AspNetHostingPermissionLevel.Minimal)> _
Public Class SimpleTextSiteMapProvider
Inherits SiteMapProvider
Private parentSiteMapProvider As SiteMapProvider = Nothing
Private simpleTextProviderName As String = Nothing
Private sourceFilename As String = Nothing
Private aRootNode As SiteMapNode = Nothing
Private siteMapNodes As ArrayList = Nothing
Private childParentRelationship As ArrayList = Nothing
' A default constructor. The Name property is initialized in the
' Initialize method.
Public Sub New()
End Sub 'New
' Implement the CurrentNode property.
Public Overrides ReadOnly Property CurrentNode() As SiteMapNode
Get
Dim currentUrl As String = FindCurrentUrl()
' Find the SiteMapNode that represents the current page.
Dim aCurrentNode As SiteMapNode = FindSiteMapNode(currentUrl)
Return aCurrentNode
End Get
End Property
' Implement the RootNode property.
Public Overrides ReadOnly Property RootNode() As SiteMapNode
Get
Return aRootNode
End Get
End Property
' Implement the ParentProvider property.
Public Overrides Property ParentProvider() As SiteMapProvider
Get
Return parentSiteMapProvider
End Get
Set(ByVal value As SiteMapProvider)
parentSiteMapProvider = Value
End Set
End Property
' Implement the RootProvider property.
Public Overrides ReadOnly Property RootProvider() As SiteMapProvider
Get
' If the current instance belongs to a provider hierarchy, it
' cannot be the RootProvider. Rely on the ParentProvider.
If Not (Me.ParentProvider Is Nothing) Then
Return ParentProvider.RootProvider
' If the current instance does not have a ParentProvider, it is
' not a child in a hierarchy, and can be the RootProvider.
Else
Return Me
End If
End Get
End Property
' Implement the FindSiteMapNode method.
Public Overrides Function FindSiteMapNode(ByVal rawUrl As String) As SiteMapNode
' Does the root node match the URL?
If RootNode.Url = rawUrl Then
Return RootNode
Else
Dim candidate As SiteMapNode = Nothing
' Retrieve the SiteMapNode that matches the URL.
SyncLock Me
candidate = GetNode(siteMapNodes, rawUrl)
End SyncLock
Return candidate
End If
End Function 'FindSiteMapNode
' Implement the GetChildNodes method.
Public Overrides Function GetChildNodes(ByVal node As SiteMapNode) As SiteMapNodeCollection
Dim children As New SiteMapNodeCollection()
' Iterate through the ArrayList and find all nodes that have the specified node as a parent.
SyncLock Me
Dim i As Integer
For i = 0 To childParentRelationship.Count - 1
Dim de As DictionaryEntry = CType(childParentRelationship(i), DictionaryEntry)
Dim nodeUrl As String = CType(de.Key, String)
Dim parent As SiteMapNode = GetNode(childParentRelationship, nodeUrl)
If Not (parent Is Nothing) AndAlso node.Url = parent.Url Then
' The SiteMapNode with the Url that corresponds to nodeUrl
' is a child of the specified node. Get the SiteMapNode for
' the nodeUrl.
Dim child As SiteMapNode = FindSiteMapNode(nodeUrl)
If Not (child Is Nothing) Then
children.Add(CType(child, SiteMapNode))
Else
Throw New Exception("ArrayLists not in sync.")
End If
End If
Next i
End SyncLock
Return children
End Function 'GetChildNodes
Protected Overrides Function GetRootNodeCore() As SiteMapNode
Return RootNode
End Function ' GetRootNodeCore()
' Implement the GetParentNode method.
Public Overrides Function GetParentNode(ByVal node As SiteMapNode) As SiteMapNode
' Check the childParentRelationship table and find the parent of the current node.
' If there is no parent, the current node is the RootNode.
Dim parent As SiteMapNode = Nothing
SyncLock Me
' Get the Value of the node in childParentRelationship
parent = GetNode(childParentRelationship, node.Url)
End SyncLock
Return parent
End Function 'GetParentNode
' Implement the ProviderBase.Initialize method.
' Initialize is used to initialize the state that the Provider holds, but
' not actually build the site map.
Public Overrides Sub Initialize(ByVal name As String, ByVal attributes As NameValueCollection)
SyncLock Me
MyBase.Initialize(name, attributes)
simpleTextProviderName = name
sourceFilename = attributes("siteMapFile")
siteMapNodes = New ArrayList()
childParentRelationship = New ArrayList()
' Build the site map in memory.
LoadSiteMapFromStore()
End SyncLock
End Sub 'Initialize
' Private helper methods
Private Function GetNode(ByVal list As ArrayList, ByVal url As String) As SiteMapNode
Dim i As Integer
For i = 0 To list.Count - 1
Dim item As DictionaryEntry = CType(list(i), DictionaryEntry)
If CStr(item.Key) = url Then
Return CType(item.Value, SiteMapNode)
End If
Next i
Return Nothing
End Function 'GetNode
' Get the URL of the currently displayed page.
Private Function FindCurrentUrl() As String
Try
' The current HttpContext.
Dim currentContext As HttpContext = HttpContext.Current
If Not (currentContext Is Nothing) Then
Return currentContext.Request.RawUrl
Else
Throw New Exception("HttpContext.Current is Invalid")
End If
Catch e As Exception
Throw New NotSupportedException("This provider requires a valid context.", e)
End Try
End Function 'FindCurrentUrl
Protected Overridable Sub LoadSiteMapFromStore()
Dim pathToOpen As String
SyncLock Me
' If a root node exists, LoadSiteMapFromStore has already
' been called, and the method can return.
If Not (aRootNode Is Nothing) Then
Return
Else
pathToOpen = HttpContext.Current.Server.MapPath("~" & "\\" & sourceFilename)
If File.Exists(pathToOpen) Then
' Open the file to read from.
Dim sr As StreamReader = File.OpenText(pathToOpen)
Try
' Clear the state of the collections and aRootNode
aRootNode = Nothing
siteMapNodes.Clear()
childParentRelationship.Clear()
' Parse the file and build the site map
Dim s As String = ""
Dim nodeValues As String() = Nothing
Dim temp As SiteMapNode = Nothing
Do
s = sr.ReadLine()
If Not s Is Nothing Then
' Build the various SiteMapNode objects and add
' them to the ArrayList collections. The format used
' is: URL,TITLE,DESCRIPTION,PARENTURL
nodeValues = s.Split(","c)
temp = New SiteMapNode(Me, _
HttpRuntime.AppDomainAppVirtualPath & "/" & nodeValues(0), _
HttpRuntime.AppDomainAppVirtualPath & "/" & nodeValues(0), _
nodeValues(1), _
nodeValues(2))
' Is this a root node yet?
If aRootNode Is Nothing AndAlso _
(nodeValues(3) Is Nothing OrElse _
nodeValues(3) = String.Empty) Then
aRootNode = temp
' If not the root node, add the node to the various collections.
Else
siteMapNodes.Add(New DictionaryEntry(temp.Url, temp))
' The parent node has already been added to the collection.
Dim parentNode As SiteMapNode = _
FindSiteMapNode(HttpRuntime.AppDomainAppVirtualPath & "/" & nodeValues(3))
If Not (parentNode Is Nothing) Then
childParentRelationship.Add(New DictionaryEntry(temp.Url, parentNode))
Else
Throw New Exception("Parent node not found for current node.")
End If
End If
End If
Loop Until s Is Nothing
Finally
sr.Close()
End Try
Else
Throw New Exception("File not found")
End If
End If
End SyncLock
Return
End Sub 'LoadSiteMapFromStore
End Class 'SimpleTextSiteMapProvider
End Namespace
using System;
using System.Configuration.Provider;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Security.Permissions;
using System.Web;
namespace Samples.AspNet.CS
{
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
public class SimpleTextSiteMapProvider : SiteMapProvider
{
private SiteMapProvider parentSiteMapProvider = null;
private string simpleTextProviderName = null;
private string sourceFilename = null;
private SiteMapNode rootNode = null;
private ArrayList siteMapNodes = null;
private ArrayList childParentRelationship = null;
// A default constructor. The Name property is initialized in the
// Initialize method.
public SimpleTextSiteMapProvider()
{
}
// Implement the CurrentNode property.
public override SiteMapNode CurrentNode
{
get
{
string currentUrl = FindCurrentUrl();
// Find the SiteMapNode that represents the current page.
SiteMapNode currentNode = FindSiteMapNode(currentUrl);
return currentNode;
}
}
// Implement the RootNode property.
public override SiteMapNode RootNode
{
get
{
return rootNode;
}
}
// Implement the ParentProvider property.
public override SiteMapProvider ParentProvider
{
get
{
return parentSiteMapProvider;
}
set
{
parentSiteMapProvider = value;
}
}
// Implement the RootProvider property.
public override SiteMapProvider RootProvider
{
get
{
// If the current instance belongs to a provider hierarchy, it
// cannot be the RootProvider. Rely on the ParentProvider.
if (this.ParentProvider != null)
{
return ParentProvider.RootProvider;
}
// If the current instance does not have a ParentProvider, it is
// not a child in a hierarchy, and can be the RootProvider.
else
{
return this;
}
}
}
// Implement the FindSiteMapNode method.
public override SiteMapNode FindSiteMapNode(string rawUrl)
{
// Does the root node match the URL?
if (RootNode.Url == rawUrl)
{
return RootNode;
}
else
{
SiteMapNode candidate = null;
// Retrieve the SiteMapNode that matches the URL.
lock (this)
{
candidate = GetNode(siteMapNodes, rawUrl);
}
return candidate;
}
}
// Implement the GetChildNodes method.
public override SiteMapNodeCollection GetChildNodes(SiteMapNode node)
{
SiteMapNodeCollection children = new SiteMapNodeCollection();
// Iterate through the ArrayList and find all nodes that have the specified node as a parent.
lock (this)
{
for (int i = 0; i < childParentRelationship.Count; i++)
{
string nodeUrl = ((DictionaryEntry)childParentRelationship[i]).Key as string;
SiteMapNode parent = GetNode(childParentRelationship, nodeUrl);
if (parent != null && node.Url == parent.Url)
{
// The SiteMapNode with the Url that corresponds to nodeUrl
// is a child of the specified node. Get the SiteMapNode for
// the nodeUrl.
SiteMapNode child = FindSiteMapNode(nodeUrl);
if (child != null)
{
children.Add(child as SiteMapNode);
}
else
{
throw new Exception("ArrayLists not in sync.");
}
}
}
}
return children;
}
protected override SiteMapNode GetRootNodeCore()
{
return RootNode;
}
// Implement the GetParentNode method.
public override SiteMapNode GetParentNode(SiteMapNode node)
{
// Check the childParentRelationship table and find the parent of the current node.
// If there is no parent, the current node is the RootNode.
SiteMapNode parent = null;
lock (this)
{
// Get the Value of the node in childParentRelationship
parent = GetNode(childParentRelationship, node.Url);
}
return parent;
}
// Implement the ProviderBase.Initialize property.
// Initialize is used to initialize the state that the Provider holds, but
// not actually build the site map.
public override void Initialize(string name, NameValueCollection attributes)
{
lock (this)
{
base.Initialize(name, attributes);
simpleTextProviderName = name;
sourceFilename = attributes["siteMapFile"];
siteMapNodes = new ArrayList();
childParentRelationship = new ArrayList();
// Build the site map in memory.
LoadSiteMapFromStore();
}
}
// Private helper methods
private SiteMapNode GetNode(ArrayList list, string url)
{
for (int i = 0; i < list.Count; i++)
{
DictionaryEntry item = (DictionaryEntry)list[i];
if ((string)item.Key == url)
return item.Value as SiteMapNode;
}
return null;
}
// Get the URL of the currently displayed page.
private string FindCurrentUrl()
{
try
{
// The current HttpContext.
HttpContext currentContext = HttpContext.Current;
if (currentContext != null)
{
return currentContext.Request.RawUrl;
}
else
{
throw new Exception("HttpContext.Current is Invalid");
}
}
catch (Exception e)
{
throw new NotSupportedException("This provider requires a valid context.",e);
}
}
protected virtual void LoadSiteMapFromStore()
{
string pathToOpen;
lock (this)
{
// If a root node exists, LoadSiteMapFromStore has already
// been called, and the method can return.
if (rootNode != null)
{
return;
}
else
{
pathToOpen = HttpContext.Current.Server.MapPath("~" + "\\" + sourceFilename);
if (File.Exists(pathToOpen))
{
// Open the file to read from.
using (StreamReader sr = File.OpenText(pathToOpen))
{
// Clear the state of the collections and rootNode
rootNode = null;
siteMapNodes.Clear();
childParentRelationship.Clear();
// Parse the file and build the site map
string s = "";
string[] nodeValues = null;
SiteMapNode temp = null;
while ((s = sr.ReadLine()) != null)
{
// Build the various SiteMapNode objects and add
// them to the ArrayList collections. The format used
// is: URL,TITLE,DESCRIPTION,PARENTURL
nodeValues = s.Split(',');
temp = new SiteMapNode(this,
HttpRuntime.AppDomainAppVirtualPath + "/" + nodeValues[0],
HttpRuntime.AppDomainAppVirtualPath + "/" + nodeValues[0],
nodeValues[1],
nodeValues[2]);
// Is this a root node yet?
if (null == rootNode &&
(null == nodeValues[3] || nodeValues[3] == String.Empty))
{
rootNode = temp;
}
// If not the root node, add the node to the various collections.
else
{
siteMapNodes.Add(new DictionaryEntry(temp.Url, temp));
// The parent node has already been added to the collection.
SiteMapNode parentNode =
FindSiteMapNode(HttpRuntime.AppDomainAppVirtualPath + "/" + nodeValues[3]);
if (parentNode != null)
{
childParentRelationship.Add(new DictionaryEntry(temp.Url, parentNode));
}
else
{
throw new Exception("Parent node not found for current node.");
}
}
}
}
}
else
{
throw new Exception("File not found");
}
}
}
return;
}
}
}
Comentários
O exemplo de código usa um arquivo delimitado por vírgula chamado SiteMap.txt que segue uma estrutura específica ao carregar informações do mapa do site.A primeira linha do arquivo representa o nó raiz do mapa do site, e as linhas subsequentes são nós filho.Cada nó filho identifica o nó pai por URL.
default.aspx,Home,MyCompany Home Page,
sale.aspx,Now On Sale,Check Out These Great Deals!,default.aspx
catalog.aspx,Online Catalog,Browse Our Many Great Items!,default.aspx
O SimpleTextSiteMapProvider fornece exemplos de implementações de todas as propriedades e métodos para a classe SiteMapProvider.
Finalmente, o SimpleTextSiteMapProvider é configurado para ser o provedor padrão no arquivo Web.config, como mostrado no exemplo de código a seguir.
<configuration>
<system.web>
<siteMap defaultProvider="SimpleTextSiteMapProvider">
<providers>
<add
name="SimpleTextSiteMapProvider"
type="<type name>"
siteMapFile = "<path>/siteMap.txt" />
</providers>
</siteMap>
</system.web>
</configuration>
Para personalizar neste exemplo, substitua o <type name> por um nome totalmente qualificado da classe que implementa o provedor de dados do mapa do site.Por exemplo, no código C# acima, você poderia substituir <type name> com Samples.AspNet.CS.SimpleTextSiteMapProvider.Se você compilar o código do provedor de dados do mapa do site e colocá-lo no diretório Bin, a sequência <type name> também deve incluir o nome do seu arquivo compilado sem a extensão de nome de arquivo.Por exemplo, se você compilou o código em C# acima em um arquivo chamado Samples.AspNet.dll, você poderia substituir <type name> com Samples.AspNet.CS.SimpleTextSiteMapProvider.Samples.AspNet.Por último, substitua o caminho relativo para o arquivo do mapa do site<path>.
Observação: |
---|
Quando você herdar do SiteMapProvider classe, ao contrário de herdam o StaticSiteMapProvider classe, você deve substituir sistema autônomo seguintes membros: GetRootNodeCore, FindSiteMapNode, GetChildNodes, e GetParentNode. |
Consulte também
Conceitos
Visão geral sobre navegação em sites do ASP.NET
Tornando navegação em sites do ASP.NET seguro