No Free Time

Because my therapist says I need to let things out

Archive for the ‘sharepoint’ Category

Calling a footer a footer

Posted by andrewmyhre on September 4, 2009

SharePoint MVP Randy Drisgill points out that if you’re creating a stylesheet for a Sharepoint site with a rule for #footer meaning, ostensibly, the footer for the page, you won’t get the result you intended.

That’s because when the guys created the SharePoint engine they decided to use the element id ‘footer’ for particular div that SharePoint outputs in the middle of your page. Nice going guys! I can’t wait to explain this to the HTML team at our agency.

Posted in sharepoint | Tagged: | Leave a Comment »

Create a list in a SharePoint site programmatically

Posted by andrewmyhre on March 21, 2009

Creating a list programmatically might be handy when you need to do this in a web part or, if you’re in the situation I was in today, you need to create a list where the template is not available on the Create page.

In my case I had a Collaboration site but I needed to create a Discussion Board – impossible using the SharePoint UI. How to get around this?

The first solution that occurred to me, and what I assumed I HAD to do, was to create a custom site definition. I had no idea how to go about doing this so this was a daunting prospect. But it occurred to me that, ultimately, I’ll only need to do this one time, maybe twice, and my users will never do this. So why go to all that trouble when the purpose of a site definition is to create a repeatable story for your end users? All I needed was a one shot hack.

So I remembered the SharePoint object model, and wrote an app. This app takes three arguments – Site URL, List Name, List Template ID. I used it to create a new discussion board in my site, it’s repeatable enough for my purposes, and it took me 5 minutes to write.

The code is provided below, but I want to hit home the point of this post – SharePoint is not as difficult as you think. There is always a simple way to do what you want to do. The difficulty is remembering to think outside the UI. I used to think that where SharePoint build was concerned I’d have to get used to telling customers ‘No’ but, as it turns out, that’s not that case at all.

CreateList.exe Source

1 using System;

2 using System.Collections.Generic;

3 using System.Linq;

4 using System.Text;

5 using Microsoft.SharePoint;

6

7 namespace CreateList

8 {

9 class Program

10 {

11 static void Main(string[] args)

12 {

13 if (args.Length == 0)

14 {

15 PrintListTemplates();

16 return;

17 }

18

19 bool validArgs = true;

20 if (!Uri.IsWellFormedUriString(args[0], UriKind.Absolute))

21 {

22 Console.WriteLine(“Arg 0 must be an absolute Sharepoint site URL e.g: http://mysite.com”);

23 validArgs = false;

24 }

25

26 int templateId=0;

27 if (!int.TryParse(args[2], out templateId))

28 {

29 Console.WriteLine(“Arg 2 must be a valid list template id from the following list:”);

30 validArgs = false;

31 PrintListTemplates();

32 }

33 if (!validArgs)

34 {

35 Console.WriteLine(“Invoke with no arguments to get a list of available SharePoint List templates”);

36 return;

37 }

38

39

40 Uri siteUrl = new Uri(args[0]);

41 string listName = args[1];

42

43 AddListToSite(siteUrl, listName, templateId);

44 }

45

46 private static void AddListToSite(Uri siteUrl, string listName, int SPListTemplateTypeId)

47 {

48 using (SPSite site = new SPSite(string.Format(“{0}”, siteUrl)))

49 {

50 SPWeb web = site.OpenWeb();

51 Guid listGuid = web.Lists.Add(listName, “”, (SPListTemplateType)SPListTemplateTypeId);

52 SPList list = web.Lists.GetList(listGuid, true);

53 }

54 }

55

56 private static void PrintListTemplates()

57 {

58 string[] typeNames = System.Enum.GetNames(typeof(SPListTemplateType));

59 Array typeValues = System.Enum.GetValues(typeof(SPListTemplateType));

60

61 int j = 0;

62

63 foreach (int i in typeValues)

64 {

65 Console.WriteLine(typeNames[j++].ToString() + ” “ + i.ToString());

66 }

67 }

68 }

69 }

Posted in .net, moss 2007, sharepoint | Tagged: , , | 1 Comment »

The Sharepoint Development Experience Part 2

Posted by andrewmyhre on February 20, 2009

In this article I’m going to explain the process of setting up a new Sharepoint solution project. The purpose of creating a Sharepoint solution is that it provides the most friction-free method of deploying and managing your custom Sharepoint code. The alternative method of deploying your custom assemblies is quite manual, it involves dropping your assemblies into the GAC on the server and modifying the web.config to allow your new custom web parts to be used by Sharepoint. It also means that when you build an updated assembly you have to manually delete the old one from the GAC and replace it. The trouble with this method is that you’re setting yourself up for pain in the form of manually maintaining your GAC which, trust me, isn’t worth it. If you screw something up you could potentially completely break your Sharepoint sites and if you don’t have the right assembly to hand you have no way to fix them again.

So anyway, moving on, let me show you the right way. This is process will seem pretty long, and I suppose it is, but you only have to do this once per project. It’s about as involved as setting up a continuous integration process.

So in this example I wanted to write a web part that would let me display a Flash movie in a page. The web part is very simple, so the purpose here is to demonstrate how I create the solution and package it up unto a ‘Sharepoint Solution Package’ so that Sharepoint can manage deployment and retraction of the assemblies for me.

1) I begin with an empty class library project.

sharepointdevelopmentexperiencepart2_01

2) The first thing I’m going to do is create three folders: ‘lib’ for reference assemblies, ‘WebParts’ for my web part classes,  and ‘Packaging’ for package information files which Sharepoint will take heed of.

sharepointdevelopmentexperiencepart2_02

3) I need to reference the Microsoft.Sharepoint.dll in order to inherit my web part classes from the WebPart class. I can find this living on a Sharepoint server in the c:\program files\common files\microsoft shared\web server extensions\12\bin folder. I’m just going to copy that file into the /lib folder inside my project:

sharepointdevelopmentexperiencepart2_03

4) I’m also going to throw log4net in there just because I’m bound to want to use it. I add a reference to both assemblies:

sharepointdevelopmentexperiencepart2_04

5) And I go ahead and create my web part. There are loads of tutorials out there for creating web parts and that’s not the focus of this article so I’m going to gloss over it, except to say all I’ve done here is inherit from System.Web.UI.WebControls.WebParts.WebPart and overridden the Render() method:

sharepointdevelopmentexperiencepart2_05

6) Okay, now we need to add two files to the /Packaging folder: manifest.xml and package.ddf. Manifest.xml is there to describe what your package is supposed to for Sharepoint – what files to add to the server, what to do with your assemblies and what controls you want to be marked as ’safe’. It looks something like this:

<?xml version=1.0 encoding=utf-8 ?>

<Solution SolutionId=[generated guid]

xmlns=http://schemas.microsoft.com/sharepoint/>

 

<Assemblies>

<Assembly DeploymentTarget=GlobalAssemblyCache Location=[assembly name].dll>

<SafeControls>

<SafeControl Assembly=[assembly name], Version=1.0.0.0, Culture=neutral, PublicKeyToken=[public key token]

Namespace=[web parts namespace]

TypeName=*

Safe=True />

</SafeControls>

</Assembly>

<Assembly DeploymentTarget=GlobalAssemblyCache Location=log4net.dll />

</Assemblies>

</Solution>

The assembly name and namespace you’ll plug in yourself, the key token is obviously where you paste your assembly’s PKT, and the GUID you can just generate yourself. We’ll generate the public key token in the next step.

7) The other file is package.ddf. We need this file because a Sharepoint Solution Package file is actually a MS Cabinet file, so we use makecab.exe to create it. The package.ddf file is the script for makecab.exe to know what files to package up, where to put them in the archive, and some other meta data about it. Here’s what the contents of my package.ddf file looks like:

.OPTION EXPLICIT ; Generate errors

.Set DiskDirectoryTemplate=CDROM

.Set CompressionType=MSZIP

.Set UniqueFiles=”ON”

.Set Cabinet=on

.Set DiskDirectory1=Package

 

;Manifest

..\..\Packaging\Manifest.xml manifest.xml

 

; Assemblies

TequilaSharepointTools.dll TequilaSharepointTools.dll

..\..\lib\log4net.dll log4net.dll

So now I have the two files in my Visual Studio project:

sharepointdevelopmentexperiencepart2_05-b

8) Now the next thing I need is to generate a public key token for my assembly, and in order to do that we need to sign the assembly. That’s really straight forward and again there are tutorials all over the place for that. Just in case here are a couple of shots:

sharepointdevelopmentexperiencepart2_06

sharepointdevelopmentexperiencepart2_07

9) Cool, now to get the public key token you can just build the assembly and drop it into your GAC, then right-click on it and view the Properties. The public key token is there. OR you can follow this genius little walkthrough to add a custom external tool to Visual Studio to discover it automatically. That’s what I did so this is what the result looked like:

sharepointdevelopmentexperiencepart2_08

Now go back and paste the key token into your manifest.xml.

10) The last piece of setting up our project is adding a post-build step to run makecab.exe and generate our Sharepoint Solution Package. Open the properties for your class library project and select the Build Events tab. In the space for post-build paste the following command:

makecab.exe /f ..\..\Packaging\Package.ddf /D CabinetNameTemplate=[YourSolutionName].wsp

sharepointdevelopmentexperiencepart2_09

Substitute [YourSolutionName] for the name of your solution, mine is TequilaSharepointTools.wsp

11) Build the solution and browse to the output folder (probably /bin/debug). You should see a new folder in there called Package. Inside there’ll be a .wsp file:

sharepointdevelopmentexperiencepart2_10

12) The .wsp file is actually a cabinet file. You can prove this by changing the extension to .cab and opening the file in a program like WinRAR:

sharepointdevelopmentexperiencepart2_11

13) Now we’re ready to deploy to Sharepoint. Copy the file to your Sharepoint server and open a terminal window on the server. You’re going to run stsadm.exe which lives in the c:\program files\common files\microsoft shared\web server extensions\12\bin folder on the server. You need to run a couple of commands on it so to save yourself some sanity you should modify the path environment variable first:

path=%path%;c:\program files\common files\microsoft shared\web server extensions\12\bin

Now the first command is to add the solution to Sharepoint:

stsadm -o addsolution -filename TequilaSharepointTools.wsp

And finally, to deploy the solution to a particular Sharepoint site:

stsadm -o deploysolution -name TequilaSharepointTools.wsp -url http://lon-dean-dev3:9003 -immediate -allowgacdeployment

14) My Flash web part is now deployed to my Sharepoint site, but before I can use it I just have to do one quick thing, which is add it to the web part library. In your Sharepoint site browse to the Site Settings page and click the Web Parts link:

sharepointdevelopmentexperiencepart2_121

In the web parts gallery click the New link:

sharepointdevelopmentexperiencepart2_131

Scroll down the web part list until you find your web part. Click the checkbox…

sharepointdevelopmentexperiencepart2_141

… and scroll back up to click the Populate Gallery button.

sharepointdevelopmentexperiencepart2_151

Finally you can now add your web part to a page!

sharepointdevelopmentexperiencepart2_161

Woot. That’s the hard work done. Now that you’ve done this it’s only a hop, skip and a jump to integrate it with continuous integration, and your development experience will be nice and simple.

Posted in sharepoint | 5 Comments »

The Sharepoint Development Experience – Part 1

Posted by andrewmyhre on January 15, 2009

I want to describe the development process involved in creating a web part for a Sharepoint site, hopefully to dispel the belief that it’s difficult and time-consuming. What I want to demonstrate is that it’s actually very simple – no more difficult than creating a custom control in ASP.Net 2.0 – provided you have set up your development infrastructure correctly.

Development infrastructure is where most of the pain associated with Sharepoint development really exists, which is why following this article I’m going to continue with a series describing how you can set up the various parts of your infrastructure to enable friction-free development.

This post, however, will show you exactly how friction-free it can be. I’m going to show the steps to build a basic web part and deploy it to your sharepoint solution in a repeatable and reversible way. I’ll also give a tour of how to customise the look-and-feel of a Sharepoint website using the Sharepoint designer. The purpose of this is show to illustrate that developing with Sharepoint isn’t really that much different to developing for a standard ASP.Net 2.0-based website.

Development

Watch me create and deploy a brand new web part to a Sharepoint server:

1. This is my out of the box Publishing Site template
01 

2. I’m going to add a web part to my site by adding a new class to my visual studio project
02

3. My class must inherit from Microsoft.SharePoint.WebPartPages.WebPart. I’m going to override the Render method to make the web part output some text. Note how similar this is to an ASP.Net custom control.
03

4.  I build the project. A post-build step creates a CAB file which can be deployed to Sharepoint. This packages up my new features/webparts so that I can manage their usage within Sharepoint and easily repeat/reverse this deployment process.
04

5.  I run a script to deploy the CAB file to Sharepoint. 
05 

6. In Sharepoint I add the Web Part to a page. If I haven’t deployed this web part before I need to Import the web part from the Site Settings menu first.
06 

7. And there it is!
07 

This development process is so simple and repeatable, it’s just like a standard ASP.Net website. What’s more when I set up source-control for my visual studio solution I can set up a continuous integration environment to automatically deploy my changes for me.

Layouts

Now I’m going to change the layout for this page. Most developers seem to believe this is an almost impossible task, or at least much more painful than editing a regular ASP.Net 2.0 Web Forms page. Well, watch:

1. My page layout
08 

2. I open up Sharepoint Designer and browse to the page I want to edit and double click. Sharepoint Designer asks me if I want to edit the content for the page or the layout for the page. I select layout. Here’s what I see:

09

There are a lot of controls on the page. Most of them have the prefix SharePointWebControls, so we can pretty easily see what they’re doing and we don’t have to be afraid. Otherwise this is just like a standard ASP.Net Web Forms page – it has stuff inside ContentPlaceHolder controls. Sharepoint assigns this page layout a master page at runtime.

3. See those ugly tables in the PlaceHolderMain ContentPlaceholderControl? I’m going to change those to divs:

 10

4. And now I’m going to edit the master page for this page layout. I know that the master page I want to edit happens to be BlueBand.master, because I chose it within the SharePoint Site Settings menu. And I also know that all master pages can be found in /catalog/masterpage in SharePoint Designer. I’ll change the tables there to divs too.
12 

5. I check-in the changes to these files (SharePoint automatically provides versioning on these files because they’re actually in the SharePoint database – more on that in another post) and reload my site homepage:
13 

Not such a visually impressive example, I know, but I just wanted to demonstrate that editing a SharePoint website isn’t really that different to building an ASP.Net website, and it’s no more difficult.

In future posts I’m going to walk through how to set up the infrastructure to be able to enjoy the development experience I demonstrated in the first section, and I also hope to demonstrate some ways to make layout editing more enjoyable, like by removing as much of the .Net cruft as possible and make your pages generate something more like semantic markup.

Posted in .net, moss 2007, sharepoint | 2 Comments »