SharePoint Development tools list

SharePoint development is not always as straight-forward as we all want it to be. However, there are a lot of tools which can make our job easier. Here is a list of some of our favorite tools for SharePoint development:


SharePoint Manager 2007
“The SharePoint Manager 2007 is a SharePoint object model explorer. It enables you to browse every site on the local farm and view every property. It also enables you to change the properties (at your own risk). This is a very powerfull tool for developers that like to know what the SharePoint holds of secrets. “

STSDEV: Simple Tools for SharePoint 2007 Development
STSDEV is a proof-of-concept utility application which demonstrates how to generate Visual Studio project files and solution files to facilitate the development and deployment of templates and components for the SharePoint 2007 platform including Windows SharePoint Services 3.0 (WSS) and Microsoft Office SharePoint Server 2007 (MOSS).”

WSPBuilder
“A SharePoint Solution Package (WSP) creation tool for WSS 3.0 & MOSS 2007”

Windows SharePoint Services 3.0 Tools: Visual Studio 2008 Extensions, Version 1.2
“Tools for developing custom SharePoint applications: Visual Studio project templates for Web Parts, site definitions, and list definitions; and a stand-alone utility program, the SharePoint Solution Generator.

U2U CAML Query Builder
“CAML (Collaborative Application Markup Language) is an XML-based query language that helps you querying, building and customizing Web sites based on Windows SharePoint Services. The XML elements define various aspects of a WSS site. The tool will help you build, test and execute your CAML Queries. “

I don’t think anybody wants to write CAML Queries ‘by hand’

SharePoint Timer Scheduler
“Sharepoint Timer Scheduler gives you a way of running your Timer Job from a list in the Root Web of your Sharepoint site. Excellent way of giving Site Administrators access to Timer Jobs so they can be run immediately or rescheduled. No need to code custom SPJobDefinition classes.”

Basically, this is a ‘tool’ which allows you to reschedule timer jobs without the need to redeploy a solution! Great!

Pako Simeonov’s Tool
Pako Simeonov wrote a great tool which fixes errors of the kind ‘Feature {Guid} for list template is not installed in this farm. The operation could not be completed’

What are your favorite tools?

Append new line to SPFieldMultiLineText in SharePoint

Do you have a multiline text box field in your SharePoint site and ever wondered how to append a new line to it? Are you confused whether you should use \r\n, Environment.NewLine or perhaps even #xD #xA to mark a line break? Allow me to save you the time and give you a straight answer.


The first thing you have to do is convert the SPListItem that represents your field into SPFieldMultiLineText.
SPFieldMultiLineText multilineField
= item.Fields.GetField(COLUMN_NAME) as SPFieldMultiLineText;

Then you can use its GetFieldValueAsHtml method to get the value in the form of HTML (which will preserve the multiple lines):
string text = multilineField.GetFieldValueAsHtml(item[COLUMN_NAME], item);

You should use ‘<br/>’ as a line break:
string sharePointNewLine = “<br/>”;
text = text
+ sharePointNewLine + sharePointNewLine
+ “Appended Text:” + sharePointNewLine
+ “This text is appended on a new line!”;

And after that you just update your item:
this.Web.AllowUnsafeUpdates = true;
item[COLUMN_NAME] = text;
item.Update();
this.Web.AllowUnsafeUpdates = false;

So if the original text in the field was “Test test test“, after executing this code, it would read:
Test test test

Appended Text:
This text is appended on a new line!

Simple? As long as you remember that text should be retrieved as HTML and you should use ‘<br/>’ as a line break, yes.

Here is the full code snippet, ready to use:
public void AppendTextToMultiline(SPListItem item)
{
string COLUMN_NAME = “Multiline Column Name”;
string sharePointNewLine = “<br/>”;
SPFieldMultiLineText multilineField = item.Fields.GetField(COLUMN_NAME) as SPFieldMultiLineText;

if (multilineField != null)
{
// Get the field value as HTML
string text = multilineField.GetFieldValueAsHtml(item[COLUMN_NAME], item);

// Append the text
text = text
+ sharePointNewLine + sharePointNewLine
+ “Appended Text:” + sharePointNewLine
+ “This text is appended on a new line!”;

this.Web.AllowUnsafeUpdates = true;
item[COLUMN_NAME] = text;
item.Update();
this.Web.AllowUnsafeUpdates = false;
}
}

Hope this helps!

Beware using GetFieldValueAsHtml or GetFormattedValue with DateTime fields

Watch out when using GetFieldValueAsHtml or GetFormattedValue with SharePoint DateTime fields! They both expect the value to be in UTC! However, SPListItem[FieldName] returns its value in Local Time zone and marks it as Unspecified.


Basically, what you have to do prior to calling one of the two methods above is make sure your time is in UTC:

DateTime localTime = (DateTime)listItem[“SomeDateTime”];
DateTime universalTime = this.Web.RegionalSettings.TimeZone.LocalTimeToUTC(localTime);
string correctlyConverted = listItem[“SomeDateTime”].GetFieldValueAsHtml(universalTime);

The right way to SPWeb.EnsureUser in SharePoint

At some point of time you may need to call (SPWeb).EnsureUser from your custom SharePoint web application. But this method can not be called by everyone, as it requires some high level permissions. You may also get an error similar to this one:


Your solution is to wrap the EnsureUser within RunWithElevatedPrivileges call. However, there is a big catch. If you use instances of SPSite or SPWeb, obtained prior to the RunWithElevatedPrivileges block, it won’t work as expected because they are already associated to a non-elevated security context.

To illustrate it with code, here is WRONG usage of RunWithElevatedPrivileges:
SPWeb web = [… somehow obtained here…];

SPSecurity.RunWithElevatedPrivileges(delegate()
{
// NOTE: Wrong, do not use
SPUser someUser = web.EnsureUser(web.CurrentUser.LoginName);
});

And here is a CORRECT one:
SPWeb web = [… somehow obtained here…];

SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite elevatedSite = new SPSite(web.Site.ID))
{
SPWeb elevatedWeb = elevatedSite.OpenWeb(web.ID);
SPUser someUser = elevatedWeb.EnsureUser(web.CurrentUser.LoginName);
}
});

Basically we used the IDs of the Web and Site objects, obtained prior to the elevated block, and used them to create Site and Web object within the elevated context.

SPTimerScheduler for SharePoint Improvement

At some point of time, you will need to create a Timer Job (scheduled task) for your custom SharePoint web solution. For example, you may need it to synchronize two systems.

Out of the box, you can create a SharePoint timer job, by inheriting the SPJobDefinition class and then creating a timer job installer, by inheriting SPFeatureReceiver. What this basically does is, during the activation of your feature, the installer will kick in and add your timer job to SharePoint timer jobs list. On deactivation of the feature, the timer job will be ‘uninstalled’. This is associated to a huge inconvenience – you can’t change the schedule of your task, unless you change your source code and redeploy. In a production environment this may cause a big stir.


This is where you can use SPTimerScheduler! It is really convenient and easy to install. After deploying the solution and activating the feature, you get a ‘TimerJobSchedule’ list, where you can define all your timer jobs. You just ‘point’ to the assembly, class and method you want to execute, pass constructor parameters (optional) and you are done! It allows for simple and easy task (re)scheduling, which is generally why you want to use this solution in the first place.

If there is one nice thing about the native SharePoint timer jobs, it is the fact that if your code throws an exception during execution, it will be logged by the SharePoint timer service in the Event Log. This is missing from SPTimerScheduler!

The purpose of this article is to show you how to extend this custom solution functionality so you can see what the error was, if any.

First, you need to download the source code of SPTimerScheduler from here. As of right now, the latest release is 1.1.0.0.

After you download the source, open SharePointerTimerJobScheduler.sln in Visual Studio. It may prompt you to remove the version control associated to the project, to which you agree.

We will start by adding one more column to the ‘TimerJobSchedule’ list, which will store the latest Exception message. Please note that the project stores the list template as TimerJobSchedule.stp file, which you can not edit directly. Generally, what you have to do is import the stp file to SharePoint, create an instance of this list type, edit it by adding one more column – LastExceptionMessage (multiline, plain) and then export it again. Overwrite the old stp file with the newly exported one. Here are detailed instructions:

1) Go to your SharePoint web site -> Site Actions -> Site Settings. Under ‘Galleries’, click on ‘List Templates’.

2) Click Upload button -> “Upload Document”

3) Browse for “12\TEMPLATE\FEATURES\SharePointerTimerJobScheduler\TimerJobSchedule.stp” file from the source code and upload it.

4) Now you have added the SPTimerScheduler as a type of a custom list. Create a new instance of it. Click on ‘Create’ and under ‘Custom Lists’ you should see ‘TimerJobSchedule’. Click on it.

5) Give the list instance a name and click Create. The go to the settings of the list and under ‘Columns’ click ‘Create column’ link.

6) Name the column ‘LastExceptionMessage’ and make it of type ‘Multiple lines of text’, ‘Plain text’ and click ok.

7) Go to the Site Settings -> List templates again and delete the TimerJobSchedule list template you imported on step 3. You need to do this as preparation for the next step.

8) Now go to the list you created (of type ‘TimerJobSchedule’. Remember, you gave it a name at step 5) and open its settings. Under ‘Permissions and Management’ there is a link ‘Save list as template’. Click on it.

9) Under ‘file name’ and ‘template name’ fields call it ‘TimerJobSchedule’ as it used to be when you first imported it. Do not include content and click OK button.

10) Go to site settings again -> List templates. You should see the TimerJobSchedule template there. Click on the Name field of the item, which is a link. Save the file TimerJobSchedule.stp back to 12\TEMPLATE\FEATURES\SharePointerTimerJobScheduler.

You have now effectively added one more column to the list – LastExceptionMessage.

Now we need to edit the code too. You should have the solution open in your Visual Studio. Open TimerJobScheduler.cs for edit and go to line 140. This is the catch statement, right after the ‘RunTheTimerJobInstance(Item);‘ block. As you can see, logging logic is not yet implemented there. What you want to do is add the following code in this catch statement:

Item[“LastExceptionMessage”] = NowDateTime + ” – ” + ex.Message;

Basically it will write a time stamped exception message into the ‘LastExceptionMessage’ column you have created earlier. As you can see, we don’t even need logging components such as log4net at this point. We are using the column to store the message.

Right click the ‘SharePointerTimerJobScheduler’ project in Visual Studio and select Properties. Go to the Build Events tab and take a look at the “Post-build event command line” text box. There is an entry saying:
makecab /f solution.ddf

Change it to:
makecab /f solution.ddf

I.e. – remove the ” character at the end of the line, as it is there by mistake (I guess).

There is also an error in TimerJobSchedulerFeature.cs file of the source. Find the line:
AddListTemplateToGallery(@”C:\Program Files\Common Files\
Microsoft Shared\web server extensions\12\
TEMPLATE\FEATURES\TimerJobScheduler\TimerJobSchedule.stp”);

And replace it with:
AddListTemplateToGallery(@”C:\Program Files\Common Files\
Microsoft Shared\web server extensions\12\
TEMPLATE\FEATURES\SharePointerTimerJobScheduler\TimerJobSchedule.stp”);

I have notified the developer about those findings here.

After you are done with all of the above, rebuild the solution. The “Deployment\SharePointerTimerJobScheduler.wsp” will be refreshed. You need to redeploy it. You can do that by copying ‘SharePointerTimerJobScheduler Source\Deployment\SharePointerTimerJobScheduler.wsp‘ (which is the output of the source project) into ‘SharePointerTimerJobScheduler Release 1.1.0.0‘ (which was the release folder of the project, if you downloaded it. And you should!).

After deployment, by running ‘SharePointerTimerJobScheduler Release 1.1.0.0\Install Feature.cmd‘ (and re-activation of the ‘SharePointer Timer Job Scheduler’ site feature) make sure the ‘LastExceptionMessage‘ column is visible in your default list view, so you can monitor it for errors.

And that’s all. Now just make sure that the method you are executing as a timer job, throws a meaningful exception, which will be visualized in the list column!

Sample SharePoint project localization Part 1 of 2

Hello,

This is a step-by-step tutorial on how to create a localized SharePoint custom web application. In this first part, we will discuss the creation of the sample web application itself, while the second one, will emphasize on the localization.

Prerequisite is a Visual Studio 2008 with WSS extensions 1.3. You can also work with Visual Studio 2005, but you will have to do part of the deployment manually.

1. Start Visual Studio and create new project of type SharePoint.

I entered ‘SPLocalization’ as name for the project.

2. Select “Full Trust”

Note: Check debug tab of Project Setting to ensure it contain correct path to your SharePoint server.

3. Add new item to our project

4. Select ‘Template’ element in SharePoint section. Change file name to ‘LocalizedPage.aspx’

— @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in } –>

5. Now you should see project structure like this:

6. Create subfolder LAYOUTS under Template folder

7. Create subfolder SPLocalization under LAYOURS folder

8. Move LocalizedPage.aspx to SPLocalization folder (I use drag and drop the file). Now you should have the following structure:

9. Now let’s create a class that extends SharePoint layout pages. Add new class to your project.

10. Name it ‘LocalizedPage.aspx.cs’ and click “Add” button

<!– @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in 11. Now few other steps …

First add references to SharePoint and SharePoint.WebControls

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebControls;

Secondly make your class public, partial and derived from LayoutsPageBase

You should see something like this:

Now, since we have chosen GAC deployment model, we need to deploy our solution to Global Assembly and determine Public Key.

12. In Visual Studio Menu, Selection, Build -> Quick Deploy Solution -> Copy Binary(s)

This will compile our SharePoint project into DLL and deploy it to GAC. After deployment Output window will show that Deployment was successful:

13. Let’s go to Windows Assembly folder and find our library

If you open Properties of our assembly, you will be able to copy its public key token. In my case it was 7a1fde53a908a4fe.

We will need Public Key Token for our aspx.page.

Now, let’s return to our ASPX page.

14. Remove default text and add Page registration tag

<%@Page Language=”C#” MasterPageFile=”~/_layouts/application.master” Inherits=”{ClassName}, {Assembly}, Version=1.0.0.0, Culture=neutral, PublicKeyToken={PublicKeyToken}” %>

Now let’s replace {ClassName} with SPLocalization.LocalizedPage {Assembly} with SPLocalization {PublicKeyToken} with Public Key Token we obtained from GAC.

Now you should see something like this:

Now let’s add some content to the page and test if everything works.

15. Add ASP tag Content with ContentPlaceHolderID equals to PlaceHolderMain. Here is complete code

<asp:Content ID=”Main” ContentPlaceHolderID=”PlaceHolderMain” runat=”server”>

Test message

<!–asp:Content>

Your Localized.aspx page should look like this:

<%@Page Language=”C#” MasterPageFile=”~/_layouts/application.master” Inherits=”SPLocalization.LocalizedPage, SPLocalization, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7a1fde53a908a4fe”%>

<asp:Content ID=”Main” ContentPlaceHolderID=”PlaceHolderMain” runat=”server”>

Test message

<!–asp:Content>

16. Let’s make a full deploy. Visual Studio menu Build -> Deploy Solution.

After deployment is completed, Output window will show that Deploy was successful.

17. Now let’s go and check manually if LocalizedPage.aspx was deployed.

Browse to 12 directory (by default it is “C:\Program Files\Common Files\Microsoft Shared\web server extensions\12”) then browse to TEMPLATE, then to LAYOUTS, then to SPLocalization. You should see our LozalizedPage.aspx was successfully deployed.

Now let’s try to access this page through SharePoint

18. Open SharePoint url of your site with prefix “_layouts/SPLocalization/LocalizedPage.aspx”.

In my case, it is “http://itech-vm-spdev/_layouts/SPLocalization/LocalizedPage.aspx&#8221;

When page is loaded you should see empty area but with our magic text: Test message

Now, let’s add SPLinkButton SharePoint control

19. Change your ASPX page to include Register of Microsoft.SharePoint assembly and replace static text with SPLinkButton control.

Your ASPX page should look like this:

<%@Page Language=”C#” MasterPageFile=”~/_layouts/application.master” Inherits=”SPLocalization.LocalizedPage, SPLocalization, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7a1fde53a908a4fe”%>

<%@Register Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” Namespace=”Microsoft.SharePoint.WebControls” TagPrefix=”cc1″ %>

<asp:Content ID=”Main” ContentPlaceHolderID=”PlaceHolderMain” runat=”server”>

<cc1:SPLinkButton Text=”” runat=”server” ID=”myLink” />

<!–asp:Content>

20. Update your LocalizedPage class to include myLink definition. We will also assign Text value in OnLoad method. You class should look like this:

public partial class LocalizedPage : LayoutsPageBase

{

protected SPLinkButton myLink;

protected override void OnLoad(EventArgs e)

{

myLink.Text =”Our test link”;

}

}

21. Let’s do full deploy again

22. Once it is successfully deployed. Open LocalizedPage in the browser again. You should see that now you have a link on the page. This link is provided by SharePoint SPLinkButton control.

In the next article, we will discuss localization of the sample application we created…