URL Rewrite und der SiteMap-Provider (Request.PathInfo)

by Wolfgang Kluge Mai 13, 2009 20:03

Heute wollte ich einer meiner Seiten so umstellen, dass URL-Rewrite verwendet wird. Das ging auch recht schnell (entsprechende Links gesetzt und über Request.PathInfo die Parameter ausgelesen), allerdings stellte sich beim Testen dann heraus, dass ich ein Problem mit dem Menü hatte. Dieses konnte nun nicht mehr die aktuelle Seite markieren... Das Menü wird über eine Sitemap erstellt.

Verkürzt sieht der Code für das Menü so aus:

<asp:SiteMapDataSource ID="MenuSource" runat="server" SiteMapProvider="menu" />
<asp:Menu ID="mnu" runat="server" DataSourceID="MenuSource">

In meiner Sitemap sind die entsprechenden URLs eingetragen. Z.B.

<siteMapNode title="Startseite" url="~/default.aspx" />
<siteMapNode title="Projekte" url="~/projects.aspx"/>
<siteMapNode title="Eigene Projekte" url="~/projects.aspx/own"/>

Wird die Seite "/projects.aspx" aufgerufen, so wird der Eintrag "Projekte" entsprechend gekennzeichnet (mittels CSS-Class "AspNet-Menu-Selected"). Das hat auch noch mit "/projects.aspx?test=1" wunderbar funktioniert. Wird dagegen die Seite "/projects.aspx/test" aufgerufen, wird der entsprechende Eintrag nicht mehr gefunden, da mit Request.RawURL verglichen wird. Und da steht "/projects/test" drin.

Es ist also nur verständlich, dass der Provider den Eintrag nicht findet und dementsprechend kein Menüeintrag als aktiv gekennzeichnet werden kann. Erschwerend kommt hinzu, dass durchaus auch mal ein Treffer dabei sein kann (wie in diesem Beispiel beim Aufruf von "/projects.aspx/own").

Da hilft nur selbst den richtigen Eintrag suchen. Das ist natürlich nur nötig, wenn Request.PathInfo gefüllt ist.

protected override void OnInit( EventArgs e ) {
    base.OnInit( e );
    if( MenuSource.Provider.CurrentNode == null && !string.IsNullOrEmpty( Request.PathInfo ) ) {
        MenuSource.Provider.SiteMapResolve += new SiteMapResolveEventHandler( SiteMap_SiteMapResolve );
    }
}

private SiteMapNode SiteMap_SiteMapResolve( object sender, SiteMapResolveEventArgs e ) {
    SiteMapProvider provider = sender as SiteMapProvider;
    if( provider == null ) return null;
    return provider.FindSiteMapNode( e.Context.Request.AppRelativeCurrentExecutionFilePath );
}

Sobald MenuSource.Provider.CurrentNode == null ist und in Request.PathInfo etwas steht, wird auf das Ereignis SiteMapResolve des Providers reagiert. Dort wird nach einem Eintrag im aktuellen SiteMapProvider gesucht, der nur dem Pfad (ohne PathInfo-Angaben) entspricht.

Wenn man das Menü innerhalb eines Controls hat (wo es hingehört *g*), muss der Code auch nur 1x angegeben werden.

Kommentare

Kommentare sind geschlossen

Powered by BlogEngine.NET 1.6.1.6
Theme by Mads Kristensen | Modified by Mooglegiant and me ;)