SharePoint: Setting value of readonly fields programmatically

When created items in SharePoint via the object model, you can convert a readonly property of that field to be false in order to allow you to set the value of that field. This is particularly useful for setting created and modified dates (all SharePoint lists retain these).

// get the list and set modified property to allow writing
SPWeb web = new SPSite("http://url/to/web").OpenWeb();
SPList selectedList = web.Lists["listname"];
selectedList.Fields["Modified"].ReadOnlyField = false;
selectedList.Fields["Modified"].Update();

// set the item
SPItem newItem = selectedList.Items[0];
newItem["Modified"] = DateTime.Now;
newItem.Update();

// Set readonly back to true
selectedList.Fields["Modified"].ReadOnlyField = true;
selectedList.Fields["Modified"].Update();

SharePoint 2007: Installing Features

To install a feature in SharePoint 2007, do the following:

  1. copy the feature folder into the C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES folder. Ensure that the feature manifest (feature.xml) exists within that folder.
  2. If stsadm is not in your path, open up a command prompt and navigate to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN
  3. Run the command: stsadm -o installfeature -filename FeatureFolderNameHere\feature.xml (note that the path must be relative to the feature folder C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES and cannot be full path).
  4. To activate the feature, run the command: stsadm -o activatefeature -filename FeatureFolderNameHere\feature.xml -url http://nameofsharepointserver
  5. Do an iisreset for for good measure (not sure if its actually required).

Related Links
http://www.sharepointblogs.com/tonstegeman/archive/2006/07/18/9314.aspx
http://www.sharepointblogs.com/tbaginski/archive/2006/06/02/8062.aspx

Creating GUIDs

A Globally Unique Identifier (GUID) is a 128bit number created by windows. They are normally based on ip address, mac address, time and some other various settings and so can be considered unique across different machines (not just the one that the guid is generated on). They are used for a range of things, from identifying a particular session on a website to identifying registry dlls.

When you install visual studio 2005, guidgen.exe should be installed in C:\Program Files\Microsoft Visual Studio 8\Common7\Tools or equivalent. However on an install of VS 2005 I had, guidgen.exe was not installed.

If it is installed with VS2005, you well get an option to “generate guid” under the tools menu. If not, guidgen.exe is a standalone executable and can be copied onto your dev machine from elsewhere. Apparently, you can also create a new guid by running the following SQL: “SELECT NewID()”.

Related links
http://msdn2.microsoft.com/en-us/library/ms241442.aspx
http://www.webopedia.com/TERM/G/GUID.html

SharePoint 2007: Setting up a decent master page

There are two layers when styling up SharePoint – the master page layer, and the page layout layer. When you create a new page, the page is build on the “page layout” aspx file. Please note that an aspx file that defines the page layout does not need to be reference the masterpage – thus a masterpage doesn’t necessarily style all published pages in a website. Note that you cannot add webpartzones to the master page – if you do, you get the following error in SharePoint “Master pages cannot contain WebPartZones.”

Ok. So if i want to create a decent masterpage, I obviously want a decent css file behind it (ie not just basic text styling). Now, to create decent look and feel, your css file will normally reference images. The question is, where should these images be stored? I believe that the best place for the css file and related images is in subdirectory in the Style Library (http://localhost/Style%20Library/Forms/AllItems.aspx). As images in a css files are reference relative to the css file, and not the page calling the css file, you can easily reference images from the subdirectory (e.g background-image: url(testImage.gif);). Note – always use the browser to access the style library and add files – don’t try to look on the filesystem (only the standard SharePoint css files exist physically there). Also note that this structure also seems to also be followed by one of the first MOSS websites – http://www.hedkandi.com

Right – so here’s an outline of the procedure for applying a masterpage. Prior to the Sharepoint Beta 2 Tech Refresh, you can not apply masterpages to all site definitions. I have yet only tested this on a publishing site (see http://www.rnowik.com/blogpost/85/ for a list of site defs that permit masterpages to be applied).

  1. Create a masterpage (note that it needs to have several controls embedded in it, these are explained below and may only be relevant on a publishing website).
  2. Upload the masterpage, corresponding css file if relevant and any related images to the style library http://localhost/Style%20Library/Forms/AllItems.aspx. Note that masterpage galleries are central to SharePoint. These do not actually exist at a site level. Remember to publish and then approve.
  3. On the site that you want to apply the masterpage to, go to the then “Modify All Settings” page and click to go to the “Site Master Page Settings” page.
  4. Select the masterpage that you want to apply to the site, and if relevant select the associated css file (browse to this via the style library dialog).
  5. Click OK and the masterpage will be applied.

Note that you need to ensure that people browsing a masterpaged site, also have permissions to read the “Style Library”. If the site is to be part of an externally facing website, you will also want to set up anonymous access.

Stuff that (probably) needs to go in a masterpage
Note that i may be missing a call to an authorisation mechanism. I don’t think this is the case, but its probably worth confirming.
This should go at the top of the master page (prior to the “html” node of the html doc).

<%@ Master language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Register Tagprefix="SPSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="wssuc" TagName="Welcome" src="~/_controltemplates/Welcome.ascx" %>
<%@ Register TagPrefix="PublishingVariations" TagName="VariationsLabelMenu" src="~/_controltemplates/VariationsLabelMenu.ascx" %>
<%@ Register Tagprefix="PublishingConsole" TagName="Console" src="~/_controltemplates/PublishingConsole.ascx" %>
<%@ Register TagPrefix="PublishingSiteAction" TagName="SiteActionMenu" src="~/_controltemplates/PublishingActionMenu.ascx" %>

The following needs to go within the “head” part of the html doc

 
<asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server"/>
<SharePoint:CssRegistration name="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/Stacked.css %>" runat="server"/>
<SharePoint:CssRegistration name="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/controls.css %>" runat="server"/>
<SharePoint:ScriptLink language="javascript" name="core.js" runat="server" />
<SharePoint:ScriptLink language="javascript" name="ows.js" runat="server" />
<Sharepoint:CssLink runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderAdditionalPageHead" runat="server"/>

The following three lines need to appear in order in the body tag (i think)

 

<body onload="javascript:_spBodyOnLoadWrapper();">
<WebPartPages:SPWebPartManager runat="server" />
<form id="Form1" runat="server" onsubmit="return _spFormOnSubmitWrapper();">

The following can go anywhere within the remainder of the html doc (however note where authoring containers wrap).

<PublishingSiteAction:SiteActionMenu runat="server" />
<PublishingWebControls:AuthoringContainer id="authoringcontrols" runat="server">
    <SharePoint:DelegateControl ControlId="GlobalSiteLink1" Scope="Farm" runat="server"/>
</PublishingWebControls:AuthoringContainer>
<PublishingWebControls:AuthoringContainer id="authoringcontrols2" runat="server">
    <SharePoint:DelegateControl ControlId="GlobalSiteLink2" Scope="Farm" runat="server"/>
</PublishingWebControls:AuthoringContainer>
<PublishingWebControls:AuthoringContainer id="authoringcontrols3" runat="server">
    <wssuc:Welcome id="explitLogout" runat="server"/>
</PublishingWebControls:AuthoringContainer> <PublishingWebControls:AuthoringContainer id="authoringcontrols4" runat="server">     <PublishingConsole:Console runat="server" /> </PublishingWebControls:AuthoringContainer>
<asp:ContentPlaceHolder id="PlaceHolderPageTitleInTitleArea" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderMain" runat="server"/>

SharePoint 2003: Some example CAML queries

In SharePoint you are not supposed to directly access the database. Instead you should access data via the object model. SharePoint has its own syntax for queries named CAML (Collaborative Application Markup Language).
Example query filtering by a boolean field

<Where>
   <Eq>
      <FieldRef Name="IsCurrent"/>
      <Value Type="Boolean">1</Value>
   </Eq>
</Where>

Example query bounded by a date

<Where>
   <Leq>
      <FieldRef Name="Created" />
      <Value Type="DateTime">1979-05-05T00:00:00Z</Value>
   </Leq>
</Where>

Example query across a date range
Note that the “and” node has to wrap around both conditions. There is no “and”clause in-between the conditions (i believe that this is also true with an “or” statement).

<Where>
   <And>
      <Geq>
         <FieldRef Name="Created" />
         <Value Type="DateTime">2006-07-20T00:00:00Z</Value>
      </Geq>
      <Leq>
         <FieldRef Name="Created" />
         <Value Type="DateTime">2007-07-20T00:00:00Z</Value>
      </Leq>
   </And>
</Where>

Example query across a date range with an additional clause
Note that the “and”clause can only wrap two conditions. If you need to use any more, you will need to use multiple “and”nodes – see example below:

<Where>
   <And>
      <And>
         <Geq>
            <FieldRef Name="Created" />
            <Value Type="DateTime">2006-07-20T00:00:00Z</Value>
         </Geq>
         <Leq>
           <FieldRef Name="Created" />
           <Value Type="DateTime">2007-07-20T00:00:00Z</Value>
         </Leq>
      </And>
      <Eq>
         <FieldRef Name="ID" />
         <Value Type="Counter">1</Value>
      </Eq>
   </And>
</Where>

Note that when running a query through the object model, you may need to wrap “<Query>” around the query (im pretty sure that this isnt the case though).
Also – highly recommended is the camlbuilder available at http://www.u2u.info/SharePoint/U2U%20Community%20Tools/Forms/AllItems.aspx

Simulating target="_blank" with JavaScript

Had a requirement the other day to simulate target=”_blank” (i.e. opening a webpage in a new window) by just specifying the href attribute. This is done using JavaScript as follows (note that void(0); ensures that nothing is sent back to the page that the link exists on – i.e. the browser doesn’t try to follow the actual href):

<a href=”javascript: window.open(‘http://www.rnowik.com’); void(0);”>This is a test</a>

Note that I have only tested this in IE6.

Quick Note: udl file

I always forget the name of this extension, hence why I am blogging it. If you want to test a db connection, create a blank file with a udl extension. When you subsequently open this file it will give you dialog to setup a db connection. Once done, if you view the udl file in a text editor, you will see the resultant connection string.