Im ersten Artikel der Serie habe ich das grundlegende Konzept für eine eigene Suche vorgestellt. In diesem Artikel will ich mich dem ersten Punkt auf der Liste widmen:

  • Einen Index samt Mechanismus, der alle Seiten erfasst und zur Analyse vorhält.

Um das Konzept so einfach und übersichtlich als Möglich zu halten, habe ich für die Beispiele eine Website mit rein statischen Inhalten gewählt. Da dies jedoch lediglich die Art der Erstellung des Index betrifft, sehe ich hier kein Problem das Vorgehen auch auf Webs mit dynamische generierten Seiten anzuwenden. Es muss lediglich jede Seite über eine eindeutige URL verfügen. Wo die Übersicht der URLs gespeichert wird, in einer XML Sitemap-Datei oder über eine Sitemap-URL spielt dabei keine Rolle.

Da im vorliegendem Beispiel nur statische Seiten verwendet werden, bietet sich hier die Erstellung des Index auf Basis der Dateinamen der aspx-Seiten an. Dies lässt sich sehr einfach mit einer Rekursion durch die Verzeichnisse der Webanwendung realisieren. Da jedoch mit Sicherheit nicht alle enthaltenen Seiten, wie etwa Login, Fehlerseiten und die Suchseite, im Index erscheinen sollen, sollte eine Möglichkeit in Betracht gezogen werden diese Seiten von der Indizierung auszuschließen.
Ich habe mich hier für den Weg über einen Eintrag in der web.config entschieden, in dem alle auszuschließenden Seiten enthalten sind. Der Zugriff auf die Einträge der web.config geschieht transparent über eine Fassaden-Klasse die nach dem Singleton Entwurfsmuster implementiert ist.

Listing web.config:

<appSettings>
  <clear/>
  <!-- hier verschiedene andere Einträge -->
  <!-- Seiten die nicht von der Suche indiziert werden sollen -->
  <add key="ExcludedSites" value="Login.aspx|Error404.aspx|Search.aspx"/>
</appSettings>

Die auszuschließenden Seiten werden in der Fassaden-Klasse in einer StringCollection vorgehalten. In der Klasse SiteSearch, welche die Logik der Suche enthält, wird lediglich ein Verweis auf diese Aufzählung in einer statischen Instanz gespeichert.

/// <summary>
/// Hält eine Auflistung der Seiten, die nicht verarbeitet werden sollen.
/// </summary>
/// <remarks>n/a</remarks>
private static StringCollection excludedSites = SiteSettings.Instance.ExcludedSites;

Jetzt muss lediglich geprüft werden, ob die jeweilige Seite in der Aufzählung enthalten ist. Wenn ja, wird diese nicht im Index erfasst. Der Index ist nicht anderes als eine List<T> vom Typ string in welcher der vollständige Pfad der jeweiligen aspx-Datei gespeichert wird.

/// <summary>
/// Erzeugt die Liste der Seiten zur Verarbeitung.
/// </summary>
/// <param name="directory">
/// Eine Instanz der DirectoryInfo-Klasse, ab der die
/// Indexerstellung begonnen werden soll.
/// </param>
/// <remarks>
/// Verarbeitet rekursiv die volle Verzeichnistiefe.
/// </remarks>
private static void CreateSiteList(DirectoryInfo directory)
{
    foreach (FileInfo file in directory.GetFiles("*.aspx"))
    {
        if (!SiteSearch.excludedSites.Contains(file.Name))
        {
            SiteSearch.siteList.Add(file.FullName);
        }
    }
    foreach (DirectoryInfo dir in directory.GetDirectories())
    {
        SiteSearch.CreateSiteList(dir);
    }
}

Gestartet wird die Indexerstellung ab dem Wurzelverzeichnis der Website.

// prüfen ob die Liste Daten enthält
if (SiteSearch.siteList == null)
{
    // Liste neu erzeugen
    SiteSearch.siteList = new List<string>();
    SiteSearch.CreateSiteList(new DirectoryInfo(SiteSearch.webRoot));
}

Das Feld webRoot enthält dabei den Pfad zum Wurzelverzeichnis der Anwendung.

/// <summary>
/// Hält den absoluten Pfad zum Web.
/// </summary>
/// <remarks>n/a</remarks>
private static readonly string webRoot = HttpContext.Current.Server.MapPath("~/");

Da jetzt nur relevante Seiten erfasst wurden, muss ich später in der Analyse der Seiten keinen Gedanken mehr daran verschwenden, ob sicherheitsrelevante Seiten über die interne Suche gefunden werden oder nicht. Es empfiehlt sich auch administrative Seiten, sofern vorhanden, von der Indizierung auszuschließen.

Natürlich könnte die Konfiguration der auszuschließenden Seite über eine eigene ConfigurationSection in der web.config erfolgen. Auch die Erweiterung um den Ausschluss ganzer Verzeichnisse könnte eingebaut werden. Doch wie schon am Anfang gesagt; ich will die Beispiele einfach halten und keine fertige Lösung liefern. Wo bleibt denn da der Spaß, wenn schon alles fertig vorliegt.

Technorati-Tags: | | |

Wenn ihnen der Artikel gefallen hat oder er für sie hilfreich war, bitten "kicken" sie ihn.
kick it on dotnet-kicks.de