Thursday, June 29, 2006

I have really enjoyed learning how to use and customize Community Server. I think it is a great platform for developing community based websites. Yet, it can be difficult to work with because customizations aren't documented well. To that end, I will try to share things I have learned while customizing CS. However, my disclaimer is: I just started this type of CS customization, and while I have searched for the best way to do things, I might have missed a better way.

The basic problem I am writing about is that I have a page which is not one of the base "areas" on install (home/blogs/forums/picture/files, etc) but which I want to link to from the title-bar. I not only want a link, but that link should be highlighted when a user is located on the custom page, or in the custom area. The link should also be relative from any location from within the site, no matter if you are hosted at the root of a domain, or under a virutal directory (the kind of reference you get with the tilde in a asp:hyperlink navigateUrl in 2.0).

Link magic occurs in the SiteUrls.config configuration file. To accomplish our goal, we'll only need to edit the config file - soon I'll write an article on customizing reading the config. There's a whole lot you can do in this file, but everything is accomplished through three types of entries:

location - A location has an attribute for 'path' which is a root-relative path to a particular location in the site. For instance the weblogs location path is "/blogs/" because this is where all blog related files are located. There is also a name attribute which will identify a particular location for later reference. Finally, you can set a boolean attribute "exclude" to indicate whether or not this location is excluded from url re-writing (url re-writing is a process by which paths are canonicalized or formatted according to patterns in siteurls - possibly other stuff. You can even setup your own rewriter via the provider pattern supported for most of this type of low-level stuff in CS).

url - Indicates a path within a given location. This works out such that a page name can be given as the path, but will always be directed to that page name underneath a folder (if one exists) for a named location. To that end, a url element contains attributes for a path, and a location. Each url also has a name. A url path may also contain string format token(s), and a related 'pattern' attributes. If a pattern exists, the url rewriter will format the path accordingly.

link - the config file itself shows what these are, but the thing to understand for our current problem is that we want to use a resourceUrl, not a navigateUrl which should be reserved for external URLs only. A resourceUrl points to a named url element, and itself has a unique name by which it will be referenced in skins and master files (more on that later). The other attributes are documented well enough in the config doc.

To put it all together: First, figure out if one of the existing locations will be relevant for your link. If you have a page under the root of the site, "common" will do. If you have created a new sub-folder, you should create a location for that folder. Second, create a url element that corresponds to the proper page you want to link to within your chosen location. Finally, create the link element that references your resourceUrl (url element), and either provide a 'text' attribute, or point to a named resource string (resource strings are in the resources.xml file in the proper language sub-folder under languages) to indicate how the link should be labelled.

Once this has been done, your link will be added to the tab-strip in the title bar. In order for the correct tab to be highlighted when you are on your page, you need to include a "SelectedNavigation" control on the master or skin for that page with the 'Selected' attribute value set equal to the name of the relevant link element. If one page will serve more than one title-bar link, you can programmatically adjust the "Selected" property of the global SelectedNavigation control in the Page_Init event: