16 July, 2008

Basic setup of SharePoint Visual Studio project


Subscribe to new articles

Now, anyone who knows me will tell you that I am a big fan of doing things the hard way. Let me rephrase that. I like learning things the hard way. I'd rather hand build a .cab-file once and know how it's done than to use some fancy tool that never teaches you anything but just gets the job sort of done. I'd love to sit around and discuss that all day, but I won't. Instead I will show you how to do the basic setup of a blank solution in Visual studio so that you can start developing. If you're really good and paying attention I will share with you my preferences on tools for doing this a bit faster at the end of the article.

Another very good reason for writing this article is that I do write a lot of other articles. Rather than explaining every time how to setup and how to deploy I can just refer people here. So, if you are lead here by another article, welcome, and don't forget to go back to the original article after you are done.

Initial setup

Step 1: Start a blank Visual Studio solution with a Class library type.

Why a class library? Well, it seems the simplest. Start from scratch and you get all the control in the world.

step-1

Step 2: Delete the default Class1.cs file.

You wont need it for any of my articles. Or just rename it to whatever you want if you so desire, you still wont need it for any of my articles.

step-2

Step 3: Add a key-file to sign the assembly and create a strong name.

Go to the menu, in Project->[Your project name] properties and find the Signing tab. On the bottom section, click the checkbox called Sign the assembly.

step-3a

The drop-down box will be enabled and you can select New which in turn opens a new dialog. Type any name, create a password if you like and click Ok.

step-3b

Step 4: Build.

From the menu, click Build->Build solution. You'll get a nice, strongly named dll which you will deploy somehow. We'll get to that. No screenshots, it is one menu item click for crying out loud!

 

Deployment

Now, at this point you basically have what you need to start developing. However, at some point you will want to deploy your dll. While you are developing you will likely want to deploy several times as well. Because of this, automating deployment into the Global Assembly Cache (GAC) will save you some time.

Step 5: Automate deployment to GAC

In the Project->[Your project name] properties page you also, in addition to the Signing tab, have a Build actions tab. On that tab there is a field called Post build event command line. Paste the following into that field:

"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" /i "$(TargetPath)" /f

This just installs the dll into your GAC every time you hit Build.

step-5

 

From here on out you will go in any number of directions, which is why I won't guide you further. Note that this process is rather generic, not SharePoint specific.

Bonus for attentive readers

As promised, since you have been paying attention, and if you haven't, then shame on you, I will share with you my preferred way of setting up my SharePoint development solution. The trick is, I don't. I use a tool to do all that for me. The name of the tool is WSPBuilder, created and made freely available at CodePlex by Carsten Keutmann. You can get it here: http://codeplex.com/wspbuilder.

With the latest release, WSPBuilder integrates into Visual Studio and gives you a couple of new solution templates.

bonus-1

These templates take care of the groundwork for you when you are developing SharePoint features. The WSPBuilder Project template creates a random keyfile and signs your assembly, creates a 12-folder for you to deploy your SharePoint content to the 12-hive, but even more important is the item templates and the functionality additions that WSPBuilder provides.

When you right-click your project to add a new item you get a whole range of often created SharePoint features.

bonus-2

Adding one of these sets up everything you need, more or less, to implement the feature. All those boring tasks like finding the strong name, putting it where it is supposed to go, etc.

Even better, in a WSP-builder project you get an extra item on your content menu when you right-click the Project in the solution explorer. That menu gives you instant access to creating the WSP-file, deploying, upgrading, and uninstalling you solution, it allows you to quickly recycle the Application pools so you updates are reload and it can, by the touch of a button, attach the debugger to the worker process, allowing you to debug your custom code really easily.

bonus-3

All the tedious work is automated!

I have no idea why mr. Keutmann did not charge for his excellent solution, but I would like, hereby, to express my deepest thank-you's to him for letting everyone share this wonderful tool. By the way, he is also the author of the equally fantastic SharePoint Manager 2007, which he also lets everyone have for free: http://www.codeplex.com/spm.

Give the man free sex and beer for the rest of his life!

So, you've gotten your data out of SharePoint and now you want it back in again


Subscribe to new articles

If you read my last article on exporting SharePoint data to Excel, you will remember that getting data from SharePoint to Excel can be fairly simple. It may seem reasonable that getting data from Excel to SharePoint is equally simple. After all, you have a 'Import Spreadsheet' thing on the Create page, right? They must be doing something. And if Microsoft can do it, how hard can it be?

Turns out, its not simple at all. The way Microsoft does this is to open Excel itself using a, ActiveX control called SpreadsheetLauncher. This in turn allows you to select a range of cells, named ranges or tables. The selected cells are then returned to SharePoint and a list is created.

Granted, the Import does a very good job at creating the list and guessing what we want. For instance, if you have only single lines of text in a column, SharePoint makes that column into a single line of text field in SharePoint. However, if you have only a single row of multi line text anywhere in the column, SharePoint will make a multi line SharePoint text field. If you format a column as a date field, SharePoint will pick up on that. It will even pick up some formatting of the date, such as having a date-only format as well as date+time format, both of which will produce their respective SharePoint counterparts. Take a look at this file for some Spreadsheet import challenges for SharePoint.

However, for all its glory and magnificence, the importer does have some flaws. First of all, it does require the you have Excel installed on the client. This may not seem like such a big issue, I mean, if you have created a spreadsheet you more than likely also have Excel, right? Well, not so. More and more products, including SharePoint, are able to produce OOXML Spreadsheet files. You may edit or create the files in numerous ways, or obtain the file in numerous ways. It is not even guaranteed that you will be working on a client, you may have a situation in which you get the file from a business partner web service somewhere, sent directly into SharePoint, and no amount of begging will get your partner to install Excel on his server, not to mention script it to click the correct buttons to select the right ranges.

Second quirk, well, as good as it is, automatic field type selection has some flaws. Format the column as time and SharePoint, having no concept of a time-only field, will not have a clue what to do, and default back to single line of text. Any 'special' formatting in Excel will be completely ignored and added a single line of text. Need a special decimal count? Well, good luck, let me know if you find something, SharePoint will leave this at 'Automatic' no matter what you select.

And in any case, what about non-default field types? After all, a great feature of SharePoint is the ability to create your own field types to hold, with the exception of free sex and beer, anything you like. Want to use a custom field type in your import? Sorry, no can do. Simon says, stick with the defaults.

If you don't need custom fields and are happy with the guess work that the automatic process does, then great. Go with the import spreadsheet option. I use it a lot, it works 95% of the time.

So, why this article? Well, I want 100%. Or actually, I usually don't but at times I need to make something that SharePoint simply does not include and I need to make my own import function. I'll get you started as well.

First some gotchas. I will be using ExcelPackage again because I am too lazy to write all this stuff myself. Using ExcelPackage, though, has some major drawbacks when it comes to column types. The way Excel handles data types is by applying styles. ExcelPackage, however, has extremely limited support for these styles, in fact, the only way to set styles is to already have a style defined in the Excel file and then applying that style. These is no support for manipulating the styles or reading any configuration about the styles. One would need to work with the file directly, for instance through the OpenXML SDK. This still is tedious work; in the current version of OpenXML SDK there is still a lot of XML handcrafting to be done to create and manipulate styles.

But hey, who cares, we don't want to mimic the existing stuff, right? We want to make our own. So, let's get started.

First our scope. I want to show you, using as simple an example as possible, how to import a spreadsheet into a SharePoint list, allowing you to select how the list will be generated. This will not be production code, it is meant to illustrate and get your imagination going. If you want production code, hire me.

So, what I'll do is create a simple console application that uses ExcelPackage to read the contents of a sample spreadsheet file and for each column allow you to select, from any existing field type in your site collection, what field will be created. How you would actually implement this in production is up to you, perhaps you want to do this from a SharePoint application page, perhaps you want to create an XML-file to hold the configuration, perhaps you want to guess. Do what thou willt.

Now, start up Visual Studio and create a new .Net Console Application. I'm using C#, you use whatever rocks your boat. Pick up a copy of ExcelPackage from CodePlex, add references to Windows.SharePoint.dll and ExcelPackage.dll just as we did in the last article. Add using statements if you like, it makes the code a lot more readable. It should look something along the lines of:

    1 using System;
    2 using System.Collections.Generic;
    3 using System.Text;
    4 
    5 using System.IO;
    6 using OfficeOpenXml;
    7 using Microsoft.SharePoint;
    8 
    9 namespace ExcelImport
   10 {
   11     class Program
   12     {
   13         static void Main(string[] args)
   14         {

Further, we want to open up the Excel file to see what's inside. Feel free to not hard-code the file path, that is only stupid. Again, illustrative purposes. I'll stop saying that, so every time something seems extremely stupid, assume it is for illustrative purposes.



   15             // Open xlsx-file.
   16             FileInfo fi = new FileInfo(@"c:\Files\toImport.xlsx");
   17             if (! fi.Exists)
   18             {
   19                 throw new Exception("File does not exist");
   20             }
   21 
   22             ExcelPackage excel = new ExcelPackage(fi);
   23             ExcelWorksheet ws = excel.Workbook.Worksheets[1];
   24 
   25             int maxColumn = 0; // Keeping track of how many columns exist


With that in place, it is time to get serious.


First we need a SharePoint site and a web to work with, as well as finding the available field types for our columns:


   27             using (SPSite site = new SPSite("http://lab-s02:12000/"))
   28             {
   29                 using (SPWeb web = site.OpenWeb())
   30                 {
   31                     // Get available field type definitions
   32                     SPFieldTypeDefinitionCollection fieldtypedefs = web.FieldTypeDefinitionCollection;
   33 
 

We might as well make ourselves a few objects while we're at it:

   34                     // Have someplace to store our selections
   35                     Dictionary<string, SPFieldTypeDefinition> colTypes = new Dictionary<string,SPFieldTypeDefinition>();
   36                     Dictionary<int, string> colNames = new Dictionary<int, string>();
   37 
   38                     Boolean ColumnEmpty = false; // Just to see if we are at the end of the columns
   39                     int ColumnCounter = 1; // Keeping track of which column we are processing.
   40 


Ok, now comes the processing. We want to iterate through the columns of the Excel sheet first. For each column we should present the user with all available SPFieldTypeDefinitions that are available and then store their selection for that column. I have commented the code online so I wont have to write further comments for each of the lines.



   41                     while (!ColumnEmpty)
   42                     {
   43                         ExcelColumn col = ws.Column(ColumnCounter);
   44                         if (!col.Hidden) // Skip hidden columns
   45                         {
   46                             ExcelCell cell = ws.Cell(1, ColumnCounter); // Assume headings in first row
   47                             string ColumnTitle = cell.Value;
   48                             if (string.IsNullOrEmpty(ColumnTitle))
   49                             {
   50                                 ColumnEmpty = true; // Stop processing if we found an empty column header
   51                             }
   52                             else
   53                             {
   54                                 Boolean validSelection = false; // just to get some simple input validation
   55 
   56                                 while (!validSelection)
   57                                 {
   58                                     int selection; // to store our parsed selection
   59                                     int selectionCounter = 1; // to display a number for users to select
   60                                     string selectionString; // input frmo user
   61 
   62                                     // Communicate with the user
   63                                     Console.Clear();
   64                                     Console.WriteLine(string.Format("For column {0}, which field type would you like?", ColumnTitle));
   65 
   66                                     foreach (SPFieldTypeDefinition fieldtypedef in fieldtypedefs)
   67                                     {
   68                                         Console.WriteLine(string.Format("{0}) : {1}", selectionCounter++, fieldtypedef.TypeDisplayName));
   69                                     }
   70                                     Console.Write("Enter your selection: ");
   71                                     selectionString = Console.ReadLine();
   72 
   73                                     // Verify that we have a valid selection
   74                                     if (int.TryParse(selectionString, out selection))
   75                                     {
   76                                         if (selection > 0 && selection < fieldtypedefs.Count)
   77                                         {
   78                                             validSelection = true;
   79                                             colTypes[ColumnTitle] = fieldtypedefs[selection-1]; // Reduce by one since collection is zero-based
   80                                             colNames[ColumnCounter-1] = ColumnTitle;
   81                                         }
   82                                     }
   83 
   84 
   85                                 }
   86                                 maxColumn++; // Update highest number of columns...
   87                                 ColumnCounter++; // and advance...
   88                             }
   89                         }
   90 
   91                     }
 

That was quite a mouthful, but don't worry, the basic idea should be simple, we really just need some way of finding out what field type the user wants for each Excel column.

Now to the SharePoint stuff. We may want to delete our list if it already exists. After all, we are importing a totally new list.

   93                     // Delete the list if it already exists...
   94                     SPListCollection listColl = web.Lists;
   95                     if (listColl["MyTitle"] != null)
   96                     {
   97                         listColl["MyTitle"].Delete();
   98                     }
   99 


MyTitle, of course, should be changed. By, why do I keep repeating the 'for illustrative purposes' still...


Next, let's create our list an populate it with fields. Again I have commented inline:


  100                     // Make a new list
  101                     Guid listId = listColl.Add("MyTitle", "MyDescription " + new Random().Next(10000).ToString(), SPListTemplateType.GenericList);
  102                     SPList list = web.Lists[listId];
  103 
  104                     // Add new fields to the list
  105                     foreach (string column in colTypes.Keys)
  106                     {
  107                         SPField newField = new SPField(list.Fields, colTypes[column].TypeName, column);
  108                         // this is where you would customize your fields, ie set number of lines in multiline, set number of decimals, etc.
  109                         list.Fields.Add(newField);
  110                     }
  111 


Simple enough, eh? Well, note that I have skipped the field customization. You will want to put code there to make sure your fields work as you expect. However, I'll leave that, and quite a few other things, as an exercise.


Finally we are at the last leg, we now just need to import our data. This is messy code, but you should get the drift. What we do is iterate through each row, creating a new item in our list, and for each column (remember that colNames dictionary we create earlier?) we add the value to the item:


  112                     // Now for importing the data
  113                     int rowCounter = 2; // 2 to skip first line with titles/column names
  114 
  115                     // Check if first value row is empty. Do something better than this in production, please...
  116                     Boolean rowEmpty = string.IsNullOrEmpty(ws.Cell(rowCounter, 1).Value); 
  117 
  118                     while (!rowEmpty)
  119                     {
  120                         SPListItem item = list.Items.Add(); // New item
  121                         for (int colCounter = 1; colCounter <= maxColumn; colCounter++) // colCounter for use in Excel cell references
  122                         {
  123                             int fieldCounter = colCounter - 1; // Keeps track of our column names in colNames dictionary
  124                             Type t = item.Fields[colNames[fieldCounter]].GetType();
  125                             string typestring = t.ToString();
  126                             string fieldstring = item.Fields[colNames[fieldCounter]].StaticName;
  127 
  128                             if (t == typeof(SPFieldText)  t == typeof(SPFieldMultiLineText))
  129                             {
  130                                 // This only works for strings and simple values, folks!
  131                                 item[colNames[fieldCounter]] = ws.Cell(rowCounter, colCounter).Value;
  132                             }
  133                             else if (t == typeof(SPFieldDateTime))
  134                             {
  135                                 // Handle Dates
  136                             }
  137                             else if (t == typeof(SPFieldChoice))
  138                             {
  139                                 // Handle Choice
  140                             }
  141                             else if (t == typeof(MyField))
  142                             {
  143                                 // Handle custom field
  144                             }
  145                             else
  146                             {
  147                                 throw new Exception(string.Format("{0} is unsupported type", t.ToString()));
  148                             }
  149 
  150                         }
  151 
  152                         // Make sure item is updated
  153                         item.Update();
  154                         // And advance
  155                         rowCounter++;
  156 
  157                         // Check next row, first column to see if we should continue...
  158                         rowEmpty = string.IsNullOrEmpty(ws.Cell(rowCounter, 1).Value);
  159 
  160                     }
  161 

Note that for each of the different field types, except SPFieldText and SPFieldMultiLineText, I have not added the actual adding of the values.


The reason for this is, well, one thing is that I am still lazy, however, the more important thing is that what we get from ExcelPackage is still only text strings. You can just add that value to a Date field, you first need to parse it, which in itself is a challenge, but you also need to input the value in some manner. For most default field types, this should be easy, and you should be able to Google a ton of resources. It may or may not be just that simple for custom types. That, however, is another show.


Well, if you just close up your brackets, you should be able to compile and run. Which, and I promise that this will be the last time I mention this in this article, is not the point, since THIS IS JUST FOR ILLUSTRATIVE PURPOSES!


Untill next time, my name is Bjørn Furuknap, and I am a SharePoint architect.

15 July, 2008

Authoring for SharePointMagazine.net


Subscribe to new articles

Very few updates lately, been really busy. Hope to get up to speed now, it seems that the pace is slowing a bit.

In any case, on Wednesday, July 16th a new online magazine will launch, called SharePointMagazine.net. It will feature several articles right off the bat, including one from yours truly, called "Populating data sources in code - How to modify the data sources of a DataFormWebPart real-time and make a simple content aggregator".

Now, if everything goes according to plan I will be writing more articles for them as well. I'll update my blog once I know more, but I do plan on writing a series on Office integration, creating OOXML document from SharePoint lists and vice versa.

06 July, 2008

Access to survey data in SharePoint


Subscribe to new articles

Question from a forum:

I need help to access to a SharePoint Survey data programmatically. Every
month the user make a draw picking up 3 winners from all the users that have
been answered the survey.How can I access to the "created" and "create by" field
of the list?

Surveys are little more than complex lists, so anything you can do to lists, such as getting the author of a particular item, can be done to a survey. Check out the following code sample:


    1             using (SPSite site = new SPSite(http://lab-s02:12000/))
    2             {
    3                 using (SPWeb web = site.OpenWeb())
    4                 {
    5                     SPList survey = web.Lists["TestSurvey"];
    6                     SPListItemCollection items = survey.Items;
    7                     foreach (SPListItem item in items)
    8                     {
    9                         string author = item["Author"].ToString();
   10                         DateTime create = (DateTime)item["Created"];
   11 
   12                     }
   13 
   14                 }
   15             }

28 June, 2008

Exporting SharePoint lists to Excel, including attachments


Subscribe to new articles

Another question from a forum:


I am a newbie to sharepoint and have been tasked by my boss to create an excel or access 2003 file of all the items in a list in sharepoint 2003.


There are about 6000 items in the list with close to 2000 attachments. Using the built in "export to excel" function results in an excel file with no attachments. It is going to take me months to export the list and manually link up the attachments (after i figure how to download the attachments in the first place!).
I have done my duty and prowled the net to search for solutions, but mostly are for exporting to another sharepoint server or so, nothing much written for exporting to either access or excel 2003.


Well, as noted, SharePoint does not really have a good way of 'offlining' a list like this. If you use the Export to spreadsheet function, you will be stuck with the attachments field show as either 'True' or 'False' depending on wether or not you have or do not have attachments on an item.

After a few messages back and forth to clarify the needs (read the forum if you need details) I proposed to write a simple solution to this using code. I'll explain here.

A few quirks, though... First of all, I am not targeting SP 2003. This code runs on both WSS2.0-based and WSS 3.0-based sites.

Second I do not target Excel 2003. Creating Office 2003 solutions is a pain, or at least more pain than is needed. this is Office 2007. That was the bad news. The good news is that you can easily get an Excel 2007-format reader for Excel 2003, and since the contents are simple you should be able to copy the content to a plain 2003 document. That will take far less time than trying to write a solution for 2003. A lot less time.

So, with those quirks out of the way, here goes...

First, get a copy of ExcelPackage from CodePlex (http://www.codeplex.com/ExcelPackage). This free library makes working with Excel 2007 files from code very easy. I assume you have the rest of the SharePoint development environment set up.

Second, start your Visual Studio of choice, create a new Console Application and include references to both Microsoft.SharePoint.dll and ExcelPackage.dll. Add the using statements as required, and make sure you include System.IO as you will need to send a FileInfo object to ExcelPackage. It should look something along the lines of this:



    1 using System;
    2 using System.Collections.Generic;
    3 using System.Text;
    4 
    5 using System.IO;
    6 using OfficeOpenXml;
    7 using Microsoft.SharePoint;
    8 
    9 namespace ConsoleApplication1
   10 {
   11     class Program
   12     {
   13         static void Main(string[] args)
   14         {
 


BTW, code copy is courtecy of CopySourceAsHTML, available from http://www.jtleigh.com/people/colin/software/CopySourceAsHtml/

Now, the next step is to add the code to create the Excel file. I'll just use the spirit of the ExcelPackage samples available from the CodePlex site above:



   15             // Open or create xlsx-file.
   16             FileInfo fi = new FileInfo(@"c:\files\test.xlsx");
   17             if (fi.Exists)
   18             {
   19                 fi.Delete();
   20                 fi = new FileInfo(@"c:\files\test.xlsx");
   21             }
   22 
   23             ExcelPackage excel = new ExcelPackage(fi);
   24             ExcelWorksheet ws = excel.Workbook.Worksheets.Add("Exported SP items");
   25 


From this point on we are able to do ws.Cells(x,y).Value=something in order to manipulate the spreadsheet. Thus, our next, logical step would be to iterate through the list to add the list contents to the spreadsheet:



   26             using (SPSite site = new SPSite(http://lab-s02:12000/))
   27             {
   28                 using (SPWeb web = site.OpenWeb())
   29                 {
   30                     SPList list = web.Lists["SampleList"];
   31                     int rowIterator = 0;
   32 
   33                     foreach (SPListItem item in list.Items)
   34                     {
   35                         rowIterator++;
   36                         int columnIterator = 1;
   37 
   38                         ws.Cell(rowIterator, columnIterator++).Value = item["Title"].ToString();
   39                         ws.Cell(rowIterator, columnIterator++).Value = item["Second field"].ToString();
   40                         ws.Cell(rowIterator, columnIterator++).Value = item["Some Date"].ToString();
 



Of course, which fields you want included is up to you.



If you just finished the using-brackets here you would basically have a simple Export to Excel 2007 function, or, more correctly, Office Open XML SpreadsheetML, or something along those lines.



Now, attachments are a bit different. They are basically files stored in virtual folders in the SP Database. To access them you need to find the correct folder and iterate through the SPFiles objects that are there. Luckily, Karthick's Blog has helped us out by posting most of what we need:

 
   43                         // Get the attachments


   44                         SPFolder folder = web.Folders["Lists"].SubFolders["SampleList"].SubFolders["Attachments"].SubFolders[item.ID.ToString()];
   45                         foreach (SPFile file in folder.Files)
   46                         {
   47                             // Download to directory
   48                             string fileName = "c:\\Files\\" + file.Name;
   49                             byte[] binFile = file.OpenBinary();
   50                             System.IO.FileStream fstream = System.IO.File.Create(fileName);
   51                             fstream.Write(binFile, 0, binFile.Length);
 


Finally, or allmost, add the links to the files to your rows. I've opted to add multiple files to consecutive columns, but you may do as you please.


   53                             // Add to Excel column
   54                             ws.Cell(rowIterator, columnIterator).Value = file.Name;
   55                             Uri attachmentUri = new Uri("file://" + fileName, UriKind.Absolute);
   56                             ws.Cell(rowIterator, columnIterator).Hyperlink = attachmentUri;
   57                             columnIterator++;
   58                         }
   59 
   60                     }
   61                 }
   62             }




Last order of business is to close up. Make sure that you add the HyperlinkBase value as noted below, or your links will not work. You may, of course, substitute the actual Uri with anything you like.


   64             excel.Workbook.Properties.HyperlinkBase = new Uri(http://furuknap.blogspot.com/);
   65             excel.Save();
   66         }
   67     }
   68 }


There! Compile, run and woohoo you have an Export to excel on steroids.

I've added the non-formatted source to the comments to this post, in case you want to get a head start and not read the entire post.

Good luck!

.b

16 June, 2008

Question from a forum post


Subscribe to new articles

Question from a forum post at http://www.sharepointu.com/forums/p/4055/10709.aspx:

When creating a site template, is there a way to name a set of lists and/or document libraries based on the name of the site that is chosen when creating a new site based on a custom site template? For example, creating a new site called "Peter Pan" and then having the list and doc library (in the template) named "Peter Pan List" and "Peter Pan Doc Library" automatically after creation of the site.

/End question

Answer:
You can do this relativly easy in a featureactivated event handler, but it does require a bit of coding and provisioning the lists or sites as features or site definitions. If programming is ok with you and you are able to work with the SharePoint OM, you would go about this in one of two ways.

First you can provision the site as a site definition and have a webfeature or sitefeature that has an event handler to rename the lists. Doing this the feature way can in turn be done in one of two ways. First, you can have a 'rename lists' feature that renames lists when the feature is activated through the site definition. One downside to this is that any future lists added will not be renamed. One upside, amongst others, is that you can rename lists regardless of the lists themselves, that is, any list, regardless of how that list is provisioned through the site definition, can be renamed. The other way to do this features based is to add all lists as features and have the event handlers attached to those features. The downside is that you wont be using the 'Create' option of the site actions or view all site content page. The upside is that you can do this also after the site has been provisioned so that all new lists will be named accordingly.

The other option for renaming lists is to use a little known site provisioning object model. This technique is used by the collaboration portal in MOSS, but is available to WSS if you are willing to walk the coding lines. Again, this only works when you are provisioning sites, not for creating lists after the fact. To do this you would use the ProvisionData, ProvisionAssembly and ProvisionClass as attributes to your site definition in webtemp*.xml. If you want to go down this route, and it may be usefull anyways if only for the exercise, Anders Jacobsen has written a short article that gets you started:
http://www.pings.dk/blog/archive/2007/10/18/create-a-web-provisioner-to-enable-quote-post-site-creation-actions-quote.aspx

The huge benefit of the latter option, using the SPWebProvisioningProvider, is the flexibility you get from having complete programmatic access to site provisioning. You can add users, create on-the-fly lists, build workflows and connect them to content types or lists based on any criteria (how about appending I HATE MONDAYS to all items on a site created on Monday mornings?) or basically anything else you can do to a site. Best, or worst, part is, you dont even need a site definition outside the webtemp*.xml, you can create your entire site inside code. In fact, this is what the collaboration portal does, you will not find a SPSPORTAL site definition anywhere, but rather a reference to an assembly that does the entire provisioning through code.

Good luck!

.b

12 June, 2008

CAML is the foundation of any good SharePoint developer


Subscribe to new articles

CAML is the foundation of any good SharePoint developer and should be taught in kindergarten. CAML is really not hard, nor are views, but it does represent a different way of thinking.

Lots of tools make it easy to both generate and manipulate CAML, for instance U2U CAML Query Builder (http://www.u2u.info/SharePoint/U2U%20Community%20Tools/Forms/AllItems.aspx) or even SharePoint Manager 2007 (http://www.codeplex.com/spm), the latter is especially good for getting view and list CAML. Getting intellisense in VS is not easy, however, but you do have tools such as John Holliday's CAML.net which basically gives you a somewhat cumbersome, but incredibly powerful method of doing CAML the old OO way (http://www.codeplex.com/camldotnet).

EDIT: Oh, don't forget to check out my article on getting intellisense for CAML, at least for many parts of it: http://furuknap.blogspot.com/2008/04/intellisense-in-onet.html