Skip to content

Instantly share code, notes, and snippets.

@moaschterle
Created March 27, 2013 23:55
Show Gist options
  • Save moaschterle/5259268 to your computer and use it in GitHub Desktop.
Save moaschterle/5259268 to your computer and use it in GitHub Desktop.
using System;
using System.Configuration.Provider;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Security.Permissions;
using System.Web;
using System.Linq;
using System.Web.Caching;
using System.Configuration;
namespace DynamicSitemap
{
[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 SiteMapNode LoadSiteMapFromStore()
{
lock (this)
{
if (HttpRuntime.Cache[CacheKey()] == null)
{
//// If a root node exists, LoadSiteMapFromStore has already
//// been called, and the method can return.
//if (rootNode != null)
//{
// return;
//}
//else
//{
// Clear the state of the collections and rootNode
rootNode = null;
siteMapNodes.Clear();
childParentRelationship.Clear();
// Parse the file and build the site map
SiteMapNode temp = null;
using (MyDBContainer db = new MyDBContainer())
{
var formsmenu = (from xy in db.FormsSet orderby xy.Level select xy);
foreach (Forms myform in formsmenu)
{
// Build the various SiteMapNode objects and add
// them to the ArrayList collections. The format used
// is: URL,TITLE,DESCRIPTION,PARENTURL
temp = new SiteMapNode(this, myform.UrlDE, myform.UrlDE, myform.TitleDE, myform.TitleDE);
//HttpRuntime.AppDomainAppVirtualPath + "/" + nodeValues[0],
//HttpRuntime.AppDomainAppVirtualPath + "/" + nodeValues[0],
//nodeValues[1],
//nodeValues[2]);
// Is this a root node yet?
if (null == rootNode && (myform.Level == 0))
{
rootNode = temp;
}
// If not the root node, add the node to the various collections.
else
{
var parentnode = (from xy in db.FormsSet where xy.Id == myform.ParentID select xy).FirstOrDefault();
siteMapNodes.Add(new DictionaryEntry(temp.Url, temp));
// The parent node has already been added to the collection.
SiteMapNode parentNode =
FindSiteMapNode(parentnode.UrlDE);
if (parentNode != null)
{
childParentRelationship.Add(new DictionaryEntry(temp.Url, parentNode));
}
else
{
throw new Exception("Parent node not found for current node.");
}
}
}
}
HttpRuntime.Cache.Insert(CacheKey(), rootNode, new CacheDependency(HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["CachingCategoryDependency"])),
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(OnSiteMapChanged));
return rootNode;
}
else
{
//HttpContext.Current.Trace.Warn("BuildSiteMap", "CACHED");
return (SiteMapNode)HttpRuntime.Cache[CacheKey()];
}
}
//return;
}
void OnSiteMapChanged(string key, object item, CacheItemRemovedReason reason)
{
lock (this)
{
if (reason == CacheItemRemovedReason.DependencyChanged)
{
HttpRuntime.Cache.Remove(CacheKey());
LoadSiteMapFromStore();
}
}
}
public static string CacheKey()
{
// Hier die Logik für den Cache-Key implementieren.
// Z.B. jeweils für die ID der obersten Kategorie, wenn diese bsp. als
// Sprache deklariert wird.
//int highestID = 0;
//using (MyDBContainer db = new MyDBContainer())
//{
// highestID = (from xy in db.FormsSet select xy).Max(x => x.Id);
//}
return "mischt";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment