Implement Cross Application Navigation – Applikationübergreifende Navigation

Um eine SiteCollection übergreifenden, oder gar WebApplication übergreifende Navigation zu implementieren bedarf es einiger Kniffe. Hier ein paar Änsätze und ein erster Lösungsansatz.
————————————————–
To have a cross sitecollection or even cross web application navigation a few tricks are needed. Here is a first approach and small solution.

First of all, you will need a navigation control that is flexible enough to handle a changing cross application navigation.
I got my idea of such a control from here
http://blah.winsmarts.com/2008-1Implementing_Consistent_Navigation_across_Site_Collections.aspx

This is using a custom navigation provider.
The Microsoft.SharePoint.Navigation.SPXmlContentMapProvider.

Instead of replacing the current sitemap privider, I will add a second navigation bar and a second navigation data source provider. Just copy the existing ones and modify the ID of the navbar and modify the data source like described in the artikel mentioned above.

Trying this, I thought about the XML sitemap file and how annoying it is to edit this file manually every time when a new site is created.

That brought me to try and write some code that would do that for me. It is based on a simple ASPX website, whis is based in a subdirectory of the sharepoint /_layouts virtual directory.

On the main Application there will be a MasterNavigation list. This list contains only three columns:
ApplicationName
ApplicationURL
OrderInNavBar

An entry in this list would look like this
 

ApplicationName ApplicationURL OrderInNavBar
Portal http://portal 1

The column OrderInNavBar is still not functional in this code but you can surely guess what it would be for.

You will need to add a reference to the Microsoft.Sharepoint.dll.Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.Administration
Imports Microsoft.SharePoint.Utilities
Imports System.IO
‚create a type for storing an item from the MasterNavigationList
Public Structure MasterListItem
        Public ApplicationName As String
        Public ApplicationURL As String
        Public OrderInNavBar As Integer
    End Structure
Sub RunThroughNavigation() 
        Dim NavigationList(100, 100) As String ‚ an array to store the crawled sitecollections and sites
        Dim counter1 As Integer = 1
        Dim counter2 As Integer = 1
        Dim i, j, k As Integer
        Dim ListItem As MasterListItem ‚variable for storing an item from the MasterNavigationList
        Dim MasterListPath As String
        ‚## There will be a file named navconf.txt with only a headline and an entry to tell the main web 
        ‚## application where to lokk for the MasterList (i.e.
http://portal)
        Dim reader As StreamReader = New StreamReader(Server.MapPath(„navconf.txt“))
        MasterListPath = reader.ReadLine() ‚erste zeile lesen, aber nicht verarbeiten (überschrift)
        MasterListPath = reader.ReadLine() ‚pfad zur masterliste lesen
        reader.Close()
        Dim MasterSite As New SPSite(MasterListPath) ‚ this will open the site of the MasterList
        Dim mySite As SPWeb = MasterSite.OpenWeb()
        Dim listItems As SPListItemCollection = mySite.Lists(„MasterNavigationList“).Items
        ‚## reading the listitems from the masterlist will indicate how many web applications will be crawled ListItems.count
        ‚## this for-loop will crawl all the applications from the MasterNavigationList
        For k = 0 To listItems.Count – 1
            ListItem = ReadMasterList(k) ‚read the item from the masterlist to get the web application to be crawled (ListItem.ApplicationURL)
            Dim GlobalAdministration = New SPFarm()
            Dim URL As New System.Uri(ListItem.ApplicationURL) ‚Set web application to be crawled
            Dim webApplication As SPWebApplication = SPWebApplication.Lookup(URL) 
            Dim siteCollections As SPSiteCollection = webApplication.Sites ‚ read all the sitecollections from the current web application
            Dim siteCollection As SPSite
            For Each siteCollection In siteCollections ‚crawl the site collections
                NavigationList(counter1, 0) = siteCollection.Url ‚ put the sitecollection URLs into the array for later use
                counter1 = counter1 + 1 ‚ count how many site collections there are
            Next siteCollection

            For i = 1 To counter1 – 1 ‚crawl all the subsites of the current sitecollection in this loop
                Dim ThisCollection As New SPSite(NavigationList(i, 0))
                Dim sites As SPWebCollection = ThisCollection.AllWebs
                Dim subSite As SPWeb
                For Each subSite In sites ‚ crawl the subsites
                    NavigationList(i, counter2) = „<siteMapNode title=“““ & SPEncode.HtmlEncode(subSite.Title) _
                                                & „“““ & “ url=“““ & subSite.Url & „“““
                    ‚## put the site titles into the array and use an XML format for storage in the array
                   counter2 = counter2 + 1
                Next subSite
                counter2 = 1
            Next i
            siteCollection.Dispose()
        Next k

        For k = 0 To listItems.Count – 1
            Try ‚ put all the crawled applications and sites into different name.sitemap files
                ListItem = ReadMasterList(k)
                Dim writer As StreamWriter = New StreamWriter(Server.MapPath(ListItem.ApplicationName & „.sitemap“))
                ‚## there will be a silnge name.sitemap file for each application because you dont want to replicate the already existing main navigation
                writer.WriteLine(„<siteMap>“)
                writer.WriteLine(„<siteMapNode>“)
                For i = 1 To counter1 – 1
                    For j = 1 To 100
                        ‚## the following if-clause is to prevent writing entries from the target web application into its own sitemap file. 
                       ‚##The main navigation will stay and only the additional navigation from the other web applications will be applied
                        If NavigationList(i, 0) <> ListItem.ApplicationURL Then
                            If NavigationList(i, j) <> „“ Then
                                If j > 1 Then
                                    writer.Write(“        „)
                                Else : writer.Write(“ „)
                                End If
                                writer.Write(NavigationList(i, j))
                                If j > 1 Then
                                    writer.WriteLine(„/>“)
                                Else : writer.WriteLine(„>“)
                                End If
                            End If
                        End If
                    Next
                    If NavigationList(i, 0) <> ListItem.ApplicationURL Then writer.WriteLine(„</siteMapNode>“)
                Next
                writer.WriteLine(„</siteMapNode>“)
                writer.WriteLine(„</siteMap>“)
                writer.Close()
            Catch MyException As Exception
                Response.Write(„Mangelnde Zugriffsrechte!“)
            End Try
        Next k
        Label1.Text = „Aktionen ausgeführt!“
    End Sub
   Function ReadMasterList(ByVal itemnr As Integer) As MasterListItem ‚ function to read items from the masterlist
        Dim MasterListPath As String
        ‚## öffnen der konfigurationsdatei, um auszulesen, in welchem pfad die masterliste abgelegt ist
        Dim reader As StreamReader = New StreamReader(Server.MapPath(„navconf.txt“))
        MasterListPath = reader.ReadLine() ‚erste zeile lesen, aber nicht verarbeiten (überschrift)
        MasterListPath = reader.ReadLine() ‚pfad zur masterliste lesen
        reader.Close()
        ‚##
        ‚## Öffnen der masterliste und einlesen des übergebenen listeneintrags (itemnr)
        Dim MasterSite As New SPSite(MasterListPath)
        Dim mySite As SPWeb = MasterSite.OpenWeb()
        Dim listItems As SPListItemCollection = mySite.Lists(„MasterNavigationList“).Items
        Dim ReturnValue As MasterListItem
        ‚## einlesen der listenfelder in die variable ReturnValue (deklariert wie MasterListItem structure)
        If listItems.Count > itemnr Then
            Dim item As SPListItem = listItems(itemnr)
            ReturnValue.ApplicationName = SPEncode.HtmlEncode(item(„ApplicationName“).ToString())
            ReturnValue.ApplicationURL = SPEncode.HtmlEncode(item(„ApplicationURL“).ToString())
            ReturnValue.OrderInNavBar = SPEncode.HtmlEncode(item(„OrderInNavBar“).ToString())
        Else
            ReturnValue.ApplicationName = „No more Listentries“
        End If
        Return ReturnValue        MasterSite.Dispose()
        mySite.Dispose()

    End Function

Run the code from an ASPX website located on the sharepoint server and add the path to the name.sitemap file to every web application that will use this navigation.

Happy coding…

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert