Presenting at the Upcoming Los Angeles SharePoint User Group (LASPUG) Meeting – July 15, 2008

I will be doing a brief presentation tomorrow for the Los Angeles SharePoint User Group (LASPUG). My presentation will consist of a quick overview on some of the key classes avialable in the Search Query object model and a breif demonstration on how to use them. The meeting is virtual so you can attend from anywhere in the world. Feel free to check it out.

Fork me on GitHub

Packaging Branding and Themes for Deployment in SharePoint Environments

Last week, a colleague asked me to conduct a presentation for some colleagues to discuss best practices concerning SharePoint branding and themes. The presentation was not meant to teach anyone how to create master pages, page layouts, cascading style sheets, or write web pages, but rather, how to package branding and themes for deployment in SharePoint environments As such, I did my homework and demonstrated some approaches in a two hour virtual meeting last night. The purpose of this post is to recap the approaches and practices and provide a reference to the sample Visual Studio 2008 projects that were generated during the session.

Packaging SharePoint Themes

SharePoint themes are an interesting feature in SharePoint that allow site owners to quickly change the appearance of colors, icons, and images buy injecting an additional style sheet that overrides some of the existing styles found in the core.css style sheet. Creating a custom theme involves a couple of simple steps:

  1. Creating a new folder in the 12/TEMPLATE/THEMES directory
  2. Creating a theme.css file to override the out of the box styles defined in the core.css style sheet in the directory created in the previous step
  3. Creating a mossExtension.css file which is appended to theme.css file to create a the actual style sheet that is actually used when viewing pages in the SharePoint site
  4. Creating a <directory name>.inf file that contains some basic setup information about the theme
  5. Adding all the images and icons referenced in the custom style sheets in step 2 and 3 to the new directory created in step 1
  6. Modifying the SPTHEMES.XML file in the 12/TEMPLATE/LAYOUTS/1033 directory

A word of caution! Modifying the SPTHEMES.XML is not a recommended customization practice since this file maybe overwritten by future SharePoint service packs.

It’s easy enough to take an existing theme directory out of the 12/TEMPLATE/THEMES directory, make a copy of it, rename the directory, rename the INF file, edit the INF, theme.css, and mossExtension.css file to create a new theme. However, this approach is not practical in a production SharePoint farm. The practical approach is to use the WSS solution framework to create our own solution package to deploy the custom theme. For more information, I covered the creation of solution packages (WSP files) in detail in a previous post. Let’s take a quick look at the solution manifest for our theme package:

<?xml version=1.0encoding=utf-8 ?>
<Solution xmlns=http://schemas.microsoft.com/sharepoint/
         
DeploymentServerType=ApplicationServer
         
ResetWebServer=TRUE
         
SolutionId=D250636F-0A26-4019-8425-A5232D592C10>
 
<TemplateFiles>
 
<TemplateFile Location=LAYOUTS/1033/SPTHEMES.XML/>
 
<TemplateFile Location=LAYOUTS/1033/OOB_SPTHEMES.XML/>
 
<TemplateFile Location=THEMES/MYNEWTHEME/MYNEWTHEME.INF/>
 
<TemplateFile Location=THEMES/MYNEWTHEME/mossExtension.css/>
 
<TemplateFile Location=THEMES/MYNEWTHEME/theme.css/>
 
<!– Additional images and icons (gif, jpg, png files)
      
can be added here using <TemplateFile> elements –>
 
</TemplateFiles>
</Solution>

The solution includes a modified SPTHEMES.XML file where we added an element to define the custom theme named MYNEWTHEME. You can also see that we included a copy of the original SPTHEMES.XML file and renamed it OOB_SPTHEMES.XML since it’s always a good idea to have back up copy of the file we modified. Finally, you see the critical MYNEWTHEME.INF, mossExtension.css, and theme.css files. For the sake of brevity, additional image and icon files were excluded on purpose.

The WSP file was then generated using a directive file and the MAKECAB utility (directive files and the MAKECAB utility are also covered in my previous post) and deployed using the STSADM utility.

Packaging Branding

There are many different SharePoint Products and Technologies branding techniques. In the presentation, I demonstrated how quickly and easily we can use a solution to deploy custom style sheets, master pages, and page layouts and how we can use a feature receiver to programmatically apply the branding using the object model. Again for the sake of brevity, the demonstration illustrated how a master page can be deployed and applied. However, a similar approach can be used for page layouts, cascading style sheets, XSL files, image files, and any other branding components and artifacts.

The solution manifest to accomplish our task is relatively basic. Here it is:

<?xml version=1.0encoding=utf-8 ?>
<Solution xmlns=http://schemas.microsoft.com/sharepoint/
         
DeploymentServerType=WebFrontEnd
         
SolutionId=A250636F-0A26-4019-8425-A5232D592C10>
 
<FeatureManifests>
 
<FeatureManifest Location=MyBranding\feature.xml/>
 
</FeatureManifests>
 <Assemblies>
  <Assembly DeploymentTarget=GlobalAssemblyCache
           
Location=CustomThemeFeature.dll />
 
</Assemblies>
</Solution>

As you can see, the solution manifest only includes a feature manifest and an assembly that will be deployed to the GAC. The assembly only contains a custom feature receiver class that programatically applies the custom master page and the custom theme discussed earlier in this post.

Let’s take a look at the feature manifest:

<Feature xmlns=http://schemas.microsoft.com/sharepoint/
        
Id=D250636F-0A26-4019-8425-A5232D592C11
        
Description=My custom master page feature.
        
Title=My Custom Branding
        
ReceiverAssembly=CustomThemeFeature, Version=1.0.0.0, PublicKeyToken=1ff5d2fddf39f61b, Culture=neutral
        
ReceiverClass=CustomThemeFeature.FeatureReceiver
        
Scope=Web>
 <ElementManifests>
 
<ElementManifest Location=elements.xml/>
  <ElementFile Location=mycustom.master/>
 </ElementManifests>
</Feature>

The feature manifest is also pretty simple as it includes one element manifest and one element file. The element file is the custom master page that was created. The element manifest will declare a module that will be used to populate the master page gallery with the custom master page. An important thing to notice here is the ReceiverAssembly and ReceiverClass attributes in the Feature element. These attributes tell the WSS solution framework to use a custom assembly and feature receiver class to handle the feature related events. We will look at the feature receiver class in a bit. First lets take a look the element manifest:

<Elements xmlns=http://schemas.microsoft.com/sharepoint/>
 
<Module Name=MasterPages
         List=116
        
Url=_catalogs/masterpage>
  <File Url=mycustom.master
        Type=GhostableInLibrary />
 </Module>
</Elements>

The element manifest is simploy responsible for populating the master page gallery with the custom master page. If our solution and feature also had custom page layouts, those can be added to the master page gallery by adding File child elements to the Module element. Additionally, we could add more modules to populate the style library with custom style sheets and/or XSL files or add other media files to other SharePoint libraries.

Finally let’s take a look at the custom feature receiver class:

using Microsoft.SharePoint;

namespace CustomThemeFeature {
 public class FeatureReceiver: SPFeatureReceiver
{
 
public override void FeatureActivated(SPFeatureReceiverProperties properties) {
  
SPWeb site = (SPWeb)properties.Feature.Parent;
  
site.MasterUrl = “/_catalogs/masterpage/mycustom.master”;
  
site.CustomMasterUrl = “/_catalogs/masterpage/mycustom.master”;
  
site.ApplyTheme(“MYNEWTHEME”);
  
site.Update();
 
}
 
public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {}
  
public override void FeatureInstalled(SPFeatureReceiverProperties properties) {}
  
public override void FeatureUninstalling(SPFeatureReceiverProperties properties) {}
 
}
}

The class simply takes advantage of the feature activated event and to set the values of the master pages and apply a theme to the SPWeb object where the feature is activated.

Similar to the custom theme discussed earlier in this post, a WSP solution file was created using a directive file and the MAKECAB utility. The solution was then deployed with the STSADM utility. The feature was installed with the STSADM utility as well.

Upcoming Los Angeles SharePoint User Group Meeting – June 17, 2008

The Los Angeles SharePoint User Group (LASPUG) will be having their monthly meeting this coming Tuesday, June 17th, 2008 at 6:30 PM. The meeting is virtual so make sure you mark your calendars and attend regardless of where you are.

The meeting agenda includes two presenters:

  • Dan Kruger from Quest Software will be giving us an over view of Quest’s Development Studio for SharePoint.
  • Jim Duncan (a former MVP), Senior SharePoint Architect of ShareSquared, will be presenting a dive into Using the Business Data Catalog from SharePoint.

More information is available at http://www.laspug.org/Lists/Events%20Calendar/DispForm.aspx?ID=10

Enabling the SharePoint Safe Mode Call Stack, Disabling Custom Errors and Enabiling Compilation Debugging

When developling for SharePoint, I find myself always turning on the call stack and disabiling the custom errors in my development environment. It really does help when trying to debug run-time problems. I know there a few posts out there that describe how to do this, but I figured I would repost it as a reference for myself (which you are welcome to use).

Just remember that I do this in my development environment only. I don’t recommend changing the web.config files in any other environment.

Enabling the Call Stack

Set the value CallStack attribute in the SafeMode element in the web.config file to true.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <configuration>
  ...
  <SharePoint>
   <SafeMode MaxControls="200"
             CallStack="true"
             DirectFileDependencies="10"
             TotalFileDependencies="50"
             AllowPageLevelTrace="false">
    ...
   </SafeMode>
   ...
 </SharePoint>
 ...
</configuration>

Disabling Custom Errors

Set the value of the mode attribute in the customErrors element to Off.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <configuration>
  ...
  <system.web>
   ...
   <customErrors mode="Off" />
   ...
  </system.web>
 ...
</configuration>

Enabiling Compilation Debugging

Set the value of the debug attriute in the compilation element to true.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <configuration>
  ...
  <system.web>
   ...
   <compilation debug="true">
    ...
   </compilation>
   ...
  </system.web>
 ...
</configuration>

 Putting it all together

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <configuration>
  ...
  <SharePoint>
   <SafeMode MaxControls="200"
             CallStack="true"
             DirectFileDependencies="10"
             TotalFileDependencies="50"
             AllowPageLevelTrace="false">
    ...
   </SafeMode>
   ...
 </SharePoint>
 <system.web>
   ...
   <customErrors mode="Off" />
   ...
   <compilation debug="true">
    ...
   </compilation>
   ...
  </system.web>
 ...
</configuration>

Daniel Larson’s Best Practices for Elevated Privilege in SharePoint

[via Daniel Larson]

Daniel Larson, a MOSS MVP, has been ranting over the past few days about the use of the SPSecurity.RunWithElevatedPrivileges method. While I have been amused with his rants, I share his concerns and frustrations as a result of using the method in my SharePoint development experience and seeing the method abused and missused in many code reviews. Today, he posted a list of his best practices for gaining “elevated privileges” SharePoint.

Daniel Larson’s list of best practives for elevated privileges in SharePoint:

  • Avoid using SPSecurity.RunwithElevatedPrivilege to access the SharePoint object model. Instead, use the SPUserToken to impersonate with SPSite.
  • If you do use SPSecurity.RunwithElevatedPrivilege, dispose of all objects in the delegate. Do not pass SharePoint objects out of the RunwithElevatedPrivilege  method.
  • Only use SPSecurity.RunwithElevatedPrivilege to make network calls under the application pool identity. Don’t use it for elevation of privilege of SharePoint objects.
  • Always use the SPSite constructor with an SPUserToken to create an elevated privilege security context in SharePoint. To impersonate the system, use the SystemAccount.UserToken property of the current SPSite context, such as:
    var site = new SPSite(SPContext.Current.Site.ID,  SPContext.Current.Site.SystemAccount.UserToken);
  • Avoid passing SharePoint objects between different security contexts (SPSite instances), with the exception of the SPUserToken used in the SPSite ctor. An SPUser object created from SPSite A cannot (reliably) be passed to SPSite B. This can be the source of obscure bugs in production that are difficult to reproduce in development. For example, an SPUser reference created from SPContext.Current.Site cannot reliably be used in an elevated site context, as the user reference may take on a different meaning in the alternate context.
  • Never use elevated privilege to bypass security– always use it to work with security.
  • Restrict what assemblies can use elevated privilege by running in minimal trust, avoiding the GAC, and auditing any CAS policies deployed with vendor solutions.