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 StructureSub 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…