Clinton's profileCherry BytesBlogListsGuestbookMore Tools Help
    July 27

    Checking if a user has permission to a web

    Today I was having some problems trying to traverse a collection of webs (SPWeb objects in a SPWebCollection)and check if a user had permission to view a particular web, then print a list of the web's that a user had access to. The DoesUserHavePermissions method seemed to be the best way to check for this, however when using this and a user no longer had permission, then on the page where the list was getting printed, the user would be prompted to login (saying they had no permission). What I wanted to do was if the user didn't have permission to a web to simply not display that web in the list that I was generating.

    In order to do this I was simply using the AllWebs method of a site collection, then filtering out what a user couldn't see (using escalated privileges to get the webs out). After some searching around I found the only way to prevent the above error from happening was to post a try/catch block around the loop, then catch any System.UnauthorizedAccessException exception. As soon as I did this it worked a treat.

    So an example of this might be (please note that this is being run using elevated privileges (see here for more information about this).

            public void GetWebCollection()
            {
                SPSite mySite = new SPSite(_SiteGuid);
                SPWebCollection allWebs = mySite.AllWebs;
                _MyWebs = new List<SPWeb>();
                
                foreach (SPWeb web in allWebs)
                {
                    try
                    {
                            if (web.DoesUserHavePermissions(_CurrentUserName, SPBasePermissions.ViewListItems))
                            {
                                _MyWebs.Add(web);
                            }
                    }
                    catch (System.UnauthorizedAccessException ex) { }
                }
            }
    July 24

    Accessing stsadm.exe utility from any directory

    Basically for doing a lot of SharePoint administration you have to use the STSADM.EXE command line utility which is located in the SharePoint Hive (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN). To run it, you have to generally have to navigate to that directory which can be quite painful (unless you have setup some shortcuts to this folder).

    However thanks to this tip I found today, by adding the directory to the PATH environment variable, you are able to use this utility from any directory. 

    To do this

    1. Go to Start -> All Programs -> Control Panel -> System
    2. On the Advanced tab, click the Environment Variables button.
    3. Select the variable Path and click the Edit button.
    4. Add the following to the end of the Variable value field (don't forget the semicolon... the Path environment variable is a semicolon delimited string of directories):
      • ;C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN
    5. Click OK.

    You may have to do a restart after this, but basically you will find from now on you will be doing a lot less typing!

    July 19

    Bilingual Bloodfest

    SharePoint 2007 advertises itself as having the ability to easily create multilingual sites and publish them. After doing some digging around I discovered that this is done quite easily using Variations. 

    'Site managers can define a series of site variations and mark one such variation as the primary variation. Changes to the source variation can be automatically or manually propagated to target variations. This ensures that changes that are made in the sources are properly reconciled in all other variations. '

    You can read more about variations on the Microsoft website here.

    One little omission Microsoft decided to make in their release of SharePoint 2007, was to comment out the functionality of the Variation Picker Control which they constantly refer to in their documentation. Basically this control gives user's the ability to switch between the different variations (regions or languages) which they want to use. So for example if you wanted to add to your master page a control to give user's the ability to easily switch to the language of their choice this is the control you would use (by default the chosen language is the language of the user's browser).

    Luckily after some pretty thorough searching of the Internet I discovered this little post here by Daniel Webster which highlights that this control was commented out(for performance reasons).

    If you navigate to the the \Template\ControlTemplates folder in the hive on your SharePoint installation you will find a control called variationslabelmenu.ascx. Open this up and you will find there is a critical line commented out. If you uncomment this then the control will be back working!

    ie:

    <%@ Control Language="C#"   %>
    <%@Assembly Name="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
    <%@Register TagPrefix="CMS" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Publishing.WebControls"%>
    <cms:VariationsLabelEcbMenu id ="varlabelmenu1" DataSourceID="LabelMenuDataSource" DisplayText="<%$Resources:cms,VariationLabelMenuTitle%>" IsCallbackMode="true" runat="server" />
    <cms:VariationDataSource id="LabelMenuDataSource" LabelMenuConfiguration="1" Filter="" runat="server"/>
    
    July 16

    Creating a 'Bookmark' button in SharePoint

    If you are familiar with SharePoint Portal 2007 you will be aware that there is now the ability to have your own personalized list of links ('My Links') which you can share with everyone, just certain colleagues or even for yourself. Using the 'My Links' button in your navigation you can easily get to these links, and also add a new link.

    What I discovered today though was how you can impersonate the ability to add a new link to this list - as you might want to add a link on certain (or even every) page. This gives users the ability to click 'bookmark' or 'add to my links' easily. The link is then added to their own personal links - essentially building up their own favourites within SharePoint.

    The client script responsible for helping out here is AddToQuickLinksDialog(templateId, baseUrl). If you add this into a control you then will be able to harness all the power of the 'My Links' control from where ever you like in your portal - including the control identifying the url that you are on and adding this into your link.

    So for example to create a button for bookmarking any page, you would simply add the following into your masterpage:

    <asp:Button OnClientClick="AddToQuickLinksDialog('thisbutton','http://SharePointURL/');" 
                                    runat="server" ID="thisbutton" Text="Bookmark this page!"></asp:Button>
    July 06

    Custom Site Definitions in MOSS

    In SharePoint 2007 there are 2 different ways to create a custom site definition - the first is to create one based on an existing definition and the second way is to create a definition using code. A custom site definition will give you a base layout which your user will have automatically created for them when they create a new web using your site definition.

    The first method is very quick and easy - simply go into a site which you like the look of, go to site settings and and select 'Save Site as Template' - which is great if you have a customized team site you want other's to be able to use, or even for doing backups. Unfortunately this method just creates a ghosted version of your site, and so for future upgrading of your template is not very effective.

    The second approach, will require a little bit more work - but is far more effective as it offers more flexibility and can be changed more easily once sites have been created based on the definition. It also takes a bit of time to explain and do - hence a slightly longer post here.

    The first step you will need to do is create an xml file in the %HIVE%\1033\XML folder. The file should be prepended with webtemp, so you might end up with a file called something like WebTempClintonsCustomSite.xml. To this add some xml to define your new site definition.

    <?xml version="1.0" encoding="utf-8"?>
    <!-- _lcid="1033" _version="12.0.4518" _dal="1" -->
    <!-- _LocalBinding -->
    <Templates xmlns:ows="Microsoft SharePoint">
     <Template Name="CLINTONSCUSTOMSITEDEF" ID="10015">
        <Configuration ID="0" 
                       Title="Clintons Custom Site" 
                       Hidden="FALSE" 
                       ImageUrl="/_layouts/images/blankprev.png" 
                       DisplayCategory="Clinton"
                       AllowGlobalFeatureAssociations="False" 
                       Description="This template is used for initializing a custom workspace." > 
        
        </Configuration>
     </Template>
    </Templates>

    For more information on what you should use for these attributes it is worth Googling custom site definitions. A few examples of sites which can tell you more are here and here.

    Once you have created this you will need to create your new definition in the %HIVE%\SiteTemplates\ directory. Depending on what type of site definition you are creating, it is generally worth copying and pasting one of the other existing definitions from within this folder and renaming to your own (eg %HIVE%\SiteTemplates\ClintonsDefinition). For example if you wanted to create a new version of a team site, then you would copy the contents of 'STS'. For this example I am going to create a publishing site definition, so I have copied the 'Publishing' folder contents.

    There are really only 2 main files in this definition. The default.aspx page determines the default layout for the page. As I am using a publishing layout, this then uses my default page layout (which for me is WelcomeLinks.aspx - but modifying this is another article!) - which means I don't really have to do anything with this file.

    The main file that you will need to modify though is the ONET.xml file. There are all types of elements you can modify in here - so you will often find that you will need to take bits and pieces from various site definitions to build up the definition that you want for your file.

    The 2 main areas I find myself modifying in this file are the configuration area and the modules area. The configuration area defines what features are installed with the site. The modules define what modules are created when the site is created (for example announcements) as well as any default content to create. I have included a couple of custom samples at the end of this article to illustrate how these might be created. You will also notice that within the configuration section there is a reference to the module that the configuration is going to use.

    In my sample I have created a announcement and links list which appear on the home page of the new site. The configuration element 'Lists' defines the lists to ad. In the module I specify to create these in the 'RightColumnZone' by using a view. They will appear in that zone which is based on my publishing layout.

    The various features that I have chosen to add to the configuration are based on information that I could find from the web, and from existing site definitions. As soon as I work out what a feature does I try to add a comment so as I know what that particular feature is used for.  

    Another point to note is as this is a publishing page, you can set the status of the file you are publishing. In the module section I have set the status of the default.aspx page to 'approved'. You could set this to 'draft' if you wanted the new site custodian to approve and finalize this page before users can access it.

    All in all, creating sites this way is definitely the best way to go - though it certainly takes some fiddling around - and a fair amount of trial and error testing. I tend to modify the files in the actual hive, do an IISReset then a test deploy - then repeat the process - until I get it right. Once it is right though, I use a solution to deploy the site definition to the web. I have also included a sample manifest.xml file which shows the definition for this solution.

    A sample configuration:

     <Configuration ID="0" Name="ClintonSample">
              <Lists>
                  <List FeatureId="00BFEA71-D1CE-42de-9C63-A44004CE0104" Type="104" Title="$Resources:core,announceList;" Url="$Resources:core,lists_Folder;/$Resources:core,announce_Folder;" />
                  <List FeatureId="00BFEA71-2062-426C-90BF-714C59600103" Type="103" Title="$Resources:core,linksList;" Url="$Resources:core,lists_Folder;/$Resources:core,links_Folder;" />
              </Lists>
              <Modules>
                  <Module Name="ClintonModule" />
              </Modules>
              <SiteFeatures>
                  <!-- BasicWebParts Feature -->
                  <Feature ID="00BFEA71-1C5E-4A24-B310-BA51C3EB7A57" />
                  <!-- Publishing Prerequisites-->
                  <Feature ID="A392DA98-270B-4e85-9769-04C0FDE267AA" />
                  <!-- Office Sharepoint Server Publishing -->
                  <Feature ID="F6924D36-2FA8-4f0b-B16D-06B7250180FA" />
                  <!-- Three-state Workflow Feature -->
                  <Feature ID="FDE5D850-671E-4143-950A-87B473922DC7" />
              </SiteFeatures>
              <WebFeatures>
                  <!-- Include the common WSSListTemplateFeatures used by CMS -->
                  <Feature ID="00BFEA71-DE22-43B2-A848-C05709900100" > </Feature>
                  <Feature ID="00BFEA71-E717-4E80-AA17-D0C71B360101" > </Feature>
                  <Feature ID="00BFEA71-52D4-45B3-B544-B1C71B620109" > </Feature>
                  <Feature ID="00BFEA71-A83E-497E-9BA0-7A5C597D0107" > </Feature>
                  <Feature ID="00BFEA71-4EA5-48D4-A4AD-305CF7030140" > </Feature>
                  
                  <!-- TeamCollab Feature -->
                  <Feature ID="00BFEA71-4EA5-48D4-A4AD-7EA5C011ABE5" />
                  
                  <!-- MobilityRedirect -->
                  <Feature ID="F41CC668-37E5-4743-B4A8-74D1DB3FD8A4" />
    
                  <!-- Publishing -->
                  <Feature ID="22A9EF51-737B-4ff2-9346-694633FE4416">
                      <Properties xmlns="http://schemas.microsoft.com/sharepoint/">
                          <Property Key="ChromeMasterUrl" Value=""/>
                          <Property Key="WelcomePageUrl" Value="$Resources:cmscore,List_Pages_UrlName;/default.aspx"/>
                          <Property Key="PagesListUrl" Value=""/>
                          <Property Key="AvailableWebTemplates" Value=""/>
                          <Property Key="AvailablePageLayouts" Value=""/>
                          <Property Key="SimplePublishing" Value="true" />
                      </Properties>
                  </Feature>
                  <Feature ID="541F5F57-C847-4e16-B59A-B31E90E6F9EA">
                      <Properties xmlns="http://schemas.microsoft.com/sharepoint/">
                          <Property Key="InheritGlobalNavigation" Value="true"/>
                          <Property Key="ShowSiblings" Value="true"/>
                          <Property Key="IncludeSubSites" Value="true"/>
                      </Properties>
                  </Feature>
                  
                   <!-- Office SharePoint Server Publishing -->
                  <Feature ID="94C94CA6-B32F-4da9-A9E3-1F3D343D7ECB" />
              </WebFeatures>
          </Configuration>     

    A sample module:

      <Modules>
          <Module Name="ClintonModule" Url="$Resources:cmscore,List_Pages_UrlName;" Path="">
              <File Url="default.aspx" Type="GhostableInLibrary" Level="Approved" >
                  <Property Name="Title" Value="$Resources:cmscore,IPPT_HomeWelcomePage_Title;" />
                  <Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/WelcomeLinks.aspx, ~SiteCollection/_catalogs/masterpage/WelcomeLinks.aspx" />
                  <Property Name="ContentType" Value="$Resources:cmscore,contenttype_welcomepage_name;" />
                  <View List="$Resources:core,lists_Folder;/$Resources:core,announce_Folder;" BaseViewID="3" WebPartZoneID="RightColumnZone" WebPartOrder="1" />
                  <View List="$Resources:core,lists_Folder;/$Resources:core,links_Folder;" BaseViewID="3" WebPartZoneID="RightColumnZone" WebPartOrder="2" />
                  <AllUsersWebPart WebPartZoneID="RightColumnZone" WebPartOrder="3">
                      <![CDATA[
                       <WebPart xmlns="http://schemas.microsoft.com/WebPart/v2">
                          <Assembly>Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
                          <TypeName>Microsoft.SharePoint.WebPartPages.MembersWebPart</TypeName>
                          <Title>$Resources:wp_Members;</Title>
                          <Description>$Resources:wp_Members_Desc;</Description>
                          <FrameType>Standard</FrameType>
                          <IsVisible>false</IsVisible>
                          </WebPart>
                       ]]>
                  </AllUsersWebPart>
              </File>
          </Module>

    Sample manifest.xml file to deploy solution:

    <?xml version="1.0" encoding="utf-8" ?>
    <Solution  SolutionId="CFEBA622-799C-4e1b-995A-5D390CBE4700" xmlns="http://schemas.microsoft.com/sharepoint/">
        <TemplateFiles>
            <TemplateFile Location="1033\XML\WebTempClintonsCustomSite.xml"/>
            <TemplateFile Location="SiteTemplates\ClintonsDefinition\default.aspx"/>
            <TemplateFile Location="SiteTemplates\ClintonsDefinition\XML\ONET.XML"/>
        </TemplateFiles>
    </Solution>
    July 04

    Spell Check in SharePoint 2007

    One of the many great new features in Microsoft Officer SharePoint Server (MOSS) 2007 is the ability to use spell check for any content you add to your site. One of the NOT so great new features of MOSS 2007 is the fact that this no longer works if you lock down your permissions on your server.

    Yes, that's right - I recently locked down the permissions for 'read only' access users - essentially your viewers in the web site, which for me is any authenticated user. Unfortunately then the complaints started that when ever a user tried to do a spell check they got the error:

    “Spelling did not complete properly. If this problem persists, notify your system administrator”

    After some digging around it turned out that this is a permissions error. Turns out if you lock down permissions in SharePoint, user's can no longer view the dictionary against which SharePoint does it's spell check, and consequently it no longer works.

    There is a fix, albeit it is a slight compromise to your security configuration changes (see below). Thank goodness this is going to be fixed with Service Pack 1.

    Spell Check Permissions work around

    You will need to modify the permissions of the Group to which the user has been added, in your case the user has been given Read Permissions.

    1. Browse to the root site and go to “Site Actions”->”People and Groups”.
    2. Click on “Site Permissions”
    3. For the group (say “Visitors”) to which the user facing the problem has been added – find its “Permissions” level – it was “Read” in your case as checked during the last call.
    4. Click on “Settings”->”Permissions Levels”
    5. Click on “Read”
    6. Check the 2 check boxes for “Browse Directories  -  Enumerate files and folders in a Web site using SharePoint Designer and Web DAV interfaces.” and “Use Remote Interfaces  -  Use SOAP, Web DAV, or SharePoint Designer interfaces to access the Web site.”.
    7. Click on Submit and check if the issue reproduces.