Search This Blog

Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Monday, December 12, 2011

SharePoint Development - Improving the Performance of the For Each Loop and SPQuery Object

Recently I have been very focused on optimizing SharePoint code and so I thought I'd put together all my techniques for writing more effecient code when working with the For Each Loop and/or SPQuery Object.  If anyone has any additional techniques please post comments!

References:
http://www.zimmergren.net/archive/2008/05/04/how-to-sharepoint-queries.aspx
http://msdn.microsoft.com/en-us/library/ee558807(v=office.14).aspx
http://andreasgrabner.sys-con.com/node/1348618/mobile

1.For Large Lists Use SPQuery with For Each Loops to reduce the number of items returned:

SPList myList = SPContext.Current.Web.Lists["Example List"];
StringBuilder camlQuery = new StringBuilder();
camlQuery.Append("<Where>");
camlQuery.Append("<Eq>");

camlQuery.Append("<FieldRef Name='Category' />");
camlQuery.Append("<Value Type='Text'>");
camlQuery.Append("{Category 1}");
camlQuery.Append("</Value>");

camlQuery.Append("</Eq>");

camlQuery.Append("</Where>", ID); 


SPQuery query = new SPQuery();
query.Query = camlQuery.ToString();
//ID comes as a parameter to the method being called

SPListItemCollection listItems = myList.GetItems(query);
for(int i=0;i<100 && i< listItems.Count;i++) {
  SPListItem myListItem = listItems[i];
  htmlWriter.Write(myListItem["Title"]);}

2.Use SPListItemCollection instead of SPList:

In the example below, every time we access the Items property in the For Loop condition (myList.Items.Count) it queries all items from the Content Database - the retrieved items are never cached!
 
SPList myList = SPContext.Current.List;
for(int i=0;i<100 && i< myList.Items.Count;i++) {
  SPListItem myListItem = myList.Items[i];
  htmlWriter.Write(myListItem ["Title"]);}

In this next example the database is queried only once and from then on we work with an in-memory collection of all the retrieved list items.  In this simple example alone we saved an additional 199 trips to the database!

SPListItemCollection myItems = SPContext.Current.List.Items;
for(int i=0;i<100 && i< myItems.Count;i++) {
  SPListItem myListItem = myItems[i];
  htmlWriter.Write(myListItem["Title"]);}

3.Set the SPQuery RowLimit Property to limit the number of items returned:

SPQuery myQuery = new SPQuery();
myQuery.RowLimit = 100;
myQuery.ListItemCollectionPosition = prevItems.ListItemCollectionPosition;
//The code above will start the cursor at the previous position
SPListItemCollection items = SPContext.Current.List.GetItems(myQuery);

4.Limit the number of returned columns by using the SPQuery ViewFields property:

SPQuery myQuery = new SPQuery();
myQuery.ViewFields =
"<FieldRefName='ID'/><FieldRefName='Title'/>";

5.Limit the specific elements retrieved using CAML:

SPQuery query = new SPQuery();
query.Query = “<Where><Eq><FieldRefName=\"ID\"
/><ValueType=\"Number\">15</Value></Eq></Where>
”;

6.Query against indexed fields:

   a. Index fields are set at the list or library level (for more information click here)
   b. Index fields are stored in the Content Database – not in the Search index (for more information click here)
   c. SPQuery will only employ the first index field in your query statement
   d. Index fields add some overhead to a SharePoint list and therefore should be used judiciously

7. Use RowLimit and ListItemCollectionPosition properties to reduce the number of items returned per query by creating a paging effect:

   a. The SPQuery object provides the property ListItemCollectionPosition that allows you to specify the start position of your query page. This property can be used for any further page iteration to define the starting point of the next page.
   b. The RowLimit property allows you to specify how many items to retrieve per page.
   c. Here is a code example that combines these methods:

SPQuery query = new SPQuery();
query.RowLimit = 10; //Page size is set by RowLimit
do{  
SPListItemCollection items = SPContext.Current.List.GetItems(query);  
//do something with the page result    
query.ListItemCollectionPosition = items.ListItemCollectionPosition;}
//the code above sets the position cursor for the next iteration  
while (query.ListItemCollectionPosition != null)

8.List View Threshold and SPQuery (SharePoint 2010 Only)

   a. SPS 2010 introduces a new capability called Throttling which allows a SharePoint Farm Administrator to set a List View Threshold to limit the number of results that can be returned in a user query
   b. This same capability will allow SharePoint Farm Administrator  to enable and/or disable the developers ability to programmatically override the List View Threshold (for more information click here)
   c. Without an OrderBy clause, a SPQuery request can be blocked whenever the query is not designed to be restrictive enough to meet the List View Threshold.
   d. SharePoint Server 2010 adds a default OrderBy clause that orders by content type, which ensures that folders are returned before list items.
   e. Developers should override this behavior with one of custom OrderBy clauses so that their queries can take full advantage of using indexed fields.
   f. There are three OrderBy clauses:
      i. ContentIterator.ItemEnumerationOrderByID
      ii. ContentIterator.ItemEnumerationOrderByPath
      iii. ContentIterator.ItemEnumerationOrderByNVPField
   g. Why use the ContentIterator.ItemEnumerationOrderByNVPField Property: 
      i. Using this property overrides any OrderBy clause you may have in your SPQuery and assures that an indexed field is used for sorting
      ii. Using this property keeps your query from being blocked if your where clause is not using indexed fields and would bring back more than the throttling limit (assuming the Farm Administrator has enabled programmatic override of the List View Threshold)
      iii. Using this property overcomes the need to store results in memory and/or a temp table for sorting
      iv. Here is a code example:

StringBuilder camlQuery = new StringBuilder();
camlQuery.Append("<Where>");
camlQuery.Append("<Eq>");
camlQuery.Append("<FieldRef Name='myIndexedField' />");
camlQuery.Append("<Value Type='Text'>");
camlQuery.Append("{FieldValue}");
camlQuery.Append("</Value>");

camlQuery.Append("</Eq>");

camlQuery.Append("</Where>"); 

camlQuery.Append(ContentIterator.ItemEnumerationOrderByNVPField);

SPQuery query = new SPQuery();
query.Query = camlQuery.ToString();
ContentIterator oContentIterator = new ContentIterator();
oContentIterator.ProcessItemsInList(query, delegate(SPListItem item)
    {
        // Work on each item
    },
    delegate(SPListItem item, Exception e)
    {
        // Handle an exception that was thrown while iterating
        // Return true so that ContentIterator rethrows the exception
        return true;
    }

Writing efficient code is always best practise and since the For Each Loop and SPQuery Object are used so frequently it really pays to learn how to optimize these elements in your custom solution.

I hope that helps!

Tom

Wednesday, October 20, 2010

Develop a SharePoint 2007 Event Handler (Part 4)

This is part four of a multi-part article.

For Part 1 see this link - Part 1.
For Part 2 see this link - Part 2.
For Part 3 see this link - Part 3.


1. Below is the entire code listing for the program:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
namespace ContactUsEmailHandler
{
class EmailEventHandler : SPEmailEventReceiver
{
public override void EmailReceived(SPList List, SPEmailMessage Message, string strReceiverData)
{

//** D\I Date Variables **//
DateTime dtgToday = DateTime.Today;
string strHolidays = "";

//** D\I SPList Variables **//
string strUrl = http://MySPServer/sites/solutions/ContactUs/default.aspx;
SPSite siteCollection = new SPSite(strUrl);
SPWeb web = siteCollection.OpenWeb();
SPList listHolidays = web.Lists["Holidays"];
SPView viewHolidays = listHolidays.Views["All Items"];
SPListItemCollection itemsHolidays = listHolidays.GetItems(viewHolidays);

//** Calculate Holiday Adjustments **//
foreach (SPListItem item in itemsHolidays)
{
strHolidays = (string)item.Fields.GetField("Holiday Date").GetFieldValue(item["Holiday Date"].ToString());
if(dtgToday.ToString() == strHolidays
dtgToday.AddDays(+1).ToString() == strHolidays
dtgToday.AddDays(+2).ToString() == strHolidays)
{
dtgToday = dtgToday.AddDays(+1);
}
}

//** Extract Metadata from E-Mail **//
SPListItem Item = List.Items.Add();
{
SPListItem ListItem = List.Items.Add();
ListItem["E-mail Sender"] = Message.Sender.ToString();
ListItem["E-mail From"] = Message.Headers["From"];
ListItem["E-mail To"] = Message.Headers["To"];
ListItem["E-mail Cc"] = Message.Headers["Cc"];
ListItem["E-mail Subject"] = Message.Headers["Subject"];
ListItem["Title"] = Message.Headers["Subject"];
ListItem["E-mail Body"] = Message.HtmlBody;
ListItem["Date Received"] = dtgToday.ToShortDateString();

//** Due Date Calculations (Weekend plus 2 Business Days) **//
//Due Date Calcualtions - Mon thru Wen - +2 Days
if (dtgToday.DayOfWeek == DayOfWeek.Monday
dtgToday.DayOfWeek == DayOfWeek.Tuesday
dtgToday.DayOfWeek == DayOfWeek.Wednesday)
{
ListItem["Due Date"] = dtgToday.AddDays(+2).ToShortDateString();
}

//Due Date Calcualtions - Thu thru Sat - +4 Days
else if (dtgToday.DayOfWeek == DayOfWeek.Thursday
dtgToday.DayOfWeek == DayOfWeek.Friday
dtgToday.DayOfWeek == DayOfWeek.Saturday)
{
ListItem["Due Date"] = dtgToday.AddDays(+4).ToShortDateString();
}

//Due Date Calcualtions - Sun - +3 Days
else if (dtgToday.DayOfWeek == DayOfWeek.Sunday)
{
ListItem["Due Date"] = dtgToday.AddDays(+3).ToShortDateString();
}

//Add E-Mail Attachments
//This portion of code won't work with standard Outlook settings.
//See this article for more information - http://www.slipstick.com/problems/alwaysrtf.asp
SPAttachmentCollection itemAttachments = Item.Attachments;
SPEmailAttachmentCollection emailAttachments = Message.Attachments;
foreach (SPEmailAttachment emailAttachment in emailAttachments)
{
if (emailAttachment.FileName != "winmail.dat")
{
byte[] emailAttachmentbytes = new byte[emailAttachment.ContentStream.Length];
emailAttachment.ContentStream.Read(emailAttachmentbytes, 0, (int)emailAttachmentbytes.Length);
itemAttachments.Add(emailAttachment.FileName, emailAttachmentbytes);
ListItem["Event Log"] = emailAttachment.FileName.ToString() + " : SharePoint added an attachement.";
}
else
{
ListItem["Event Log"] = emailAttachment.FileName.ToString() + " : SharePoint cannot add these types of attachements.";
}
}

ListItem.Update(); }}}}

2. Our next step is use WSPBuilder to deploy the code. From Visual Studio, Project Explorer follow this click path: WSPBuilder -> Build WSP. This will build our WSP or Web Solution Package. Now, once again, from Visual Studio, Project Explorer follow this click path: WSPBuilder -> Deploy. This will add the solution package to the GAC, and globally deploy it to the Farm.

3. Now we have to activate the feature at the site and site collection level. To activate the feature at the site collection level go to the site collection front page and follow this click path: Site Actions -> Site Settings -> Site Collection Administration (Heading) -> Site Collection Features. From the Site Collection Features page browse down to the feature we just deployed and activate the feature by clicking on the grey button that says “Activate”.

4. To activate the feature at the site level go to the site front page and follow this click path: Site Actions -> Site Settings -> Site Administration (Heading) -> Site Features. From the Site Features page browse down to the feature we just deployed and activate the feature by clicking on the grey button that says “Activate”.

5. Now test the feature by sending an e-mail to the list with the custom event handler. Hopefully everything went well for you but if it didn’t there are a few handy tools and techniques which I use to help debug features and which I will share with you. The tools you will need are Event Handler Manager and SP Log Viewer, and the technique you will need to know is connecting to the W3WP Process.

6. Event Handler Manager is a special tool just for developing Event Handlers and this is a real must have. Event Handler Manager allows you to browse, register and remove SharePoint event handlers. This application provides the ability to register event handlers to multiple lists at once as well as remove event handlers from multiple lists at once. This tool comes packaged as a Visual Studio project which you can then add to your project folders and run from Visual Studio. Event Handler Manager is a free download available at CodePlex, you can download it here - http://speventhandlermanage.codeplex.com/.

7. SP Log Viewer is an administrative tool not a development tool, but it is very useful to SharePoint developers. SP Log Viewer enables you to easily read and filter SharePoint log data from log files. If you have ever tried to extract useful information from the SharePoint log files you know this isn’t an easy process, and that is where SP Log Viewer can help. The install is easy, just download the zip file, run the installer, and the utility will extract to its own folder. SP Log Viewer Manager is also a free download available at CodePlex, you can download it here - http://splogviewer.codeplex.com/.

8. To attach your process to the W3WP process, from Visual Studio follow this click path: Debug -> Attach to Process. Now from the Attach to Process dialog box find the W3WP process. You might find multiple W3WP processes, if so you can attach the debugger to all the instances by holding down the CTRL button during selection. If you don’t see any W3WP processes go to your browser and open a SharePoint Url so the W3WP will start to run. Then click on Refresh button and select the newly activated processes. Now you have your debugger attached to your event handler. You just have to add some breakpoints and run through the debugger step by step.

9. Well, this concludes my series of articles on how to create a Custom Event Handler for SharePoint 2007 – I hope that helps!

Thursday, October 7, 2010

Develop a SharePoint 2007 Event Handler (Part 3)

This is part three of a multi-part article.

For Part 1 see this link - Part 1.
For Part 2 see this link - Part 2.
For Part 4 see this link - Part 4.

1. To begin our development we will add the following class level variables for our due date calculations:

a. We will use this variable to determine the date offset for Holidays and weekends:

DateTime dtgToday = DateTime.Today;

b. We will use this variable to hold the holidays date from the Holidays list:

string strHolidays = "";

2. In order to work properly the application needs to know which sites, lists, libraries, views etc. it is manipulating. To accomplish this we will add the following class level variables to our application:

a. We will use a variable to hold the Absolute URL of the site (we need to use a specific site URL rather than a more general contextual reference because we only want this event handler to run on one specific site).

string strUrl = "http://MySPServer/sites/solutions/ContactUs/default.aspx";

b. Next, we need to instantiate an SPSite object based on the Absolute URL string:

SPSite siteCollection = new SPSite(strUrl);

c. And then we open the specific site passed through the URL string using the OpenWeb method of the SPSite class:

SPWeb web = siteCollection.OpenWeb();

3. Now we will just need a few more class level variables for our Holiday list and All Items view, because the application needs to pull from this list to perform it’s due date calculations:

a. The first variable will instantiate is a SPList object for the Holiday list:

SPList listHolidays = web.Lists["Holidays"];

b. Then we need to set the SPView properties to the “All Items” view:

SPView viewHolidays = listHolidays.Views["All Items"];

c. Finally we instantiate a SPListItemCollection and populate it with the items from the Holidays list, All Items view by using the GetItems method:

SPListItemCollection itemsHolidays = listHolidays.GetItems(viewHolidays);

4. The next code group will involves calculating the change to the Due Date when a Holiday falls during the two business days. Essentially, if you receive an e-mail on Tuesday, and you have two business days to respond, but Thursday is Thanksgiving, this calculation will add one more day to the due date to compensate for the holiday. The code simply loops through the collection of holiday dates from the Holidays list, All Items view, and if the Holiday date is equal to today (the day you receive the e-mail) or today + 1 (1 business day from today) or today + 2 (2 business days from today) then it will add one day to the dtgToday variable, which effectively extends the due date 1 day.

foreach (SPListItem item in itemsHolidays)
{
strHolidays = (string)item.Fields.GetField("Holiday Date").GetFieldValue(item["Holiday Date"].ToString());
if(dtgToday.ToString() == strHolidays
dtgToday.AddDays(+1).ToString() == strHolidays
dtgToday.AddDays(+2).ToString() == strHolidays)
{
dtgToday = dtgToday.AddDays(+1);
}

5. Now we will extract the metadata from the incoming e-mail and add it to the Inbox list, below is the code we need to start with. This code is pretty self explanatory; to begin with, we create a SPListItem object and set its properties equal to the collection of items in the List object. Now, you may ask, where did we declare List object? In the parameters of the overridden EmailReceived method call (see the previous article). Next we set each list item value on the left equal to the e-mail message value on the right. The only exception is the value of the Date Received field which we set equal to the dtgToday variable.

SPListItem Item = List.Items.Add();
{
SPListItem ListItem = List.Items.Add();
ListItem["E-mail Sender"] = Message.Sender.ToString();
ListItem["E-mail From"] = Message.Headers["From"];
ListItem["E-mail To"] = Message.Headers["To"];
ListItem["E-mail Cc"] = Message.Headers["Cc"];
ListItem["E-mail Subject"] = Message.Headers["Subject"];
ListItem["Title"] = Message.Headers["Subject"];
ListItem["E-mail Body"] = Message.HtmlBody;
ListItem["Date Received"] = dtgToday.ToShortDateString();

6. Now we only have one list field value left to set, the all important Due Date field. For our Due Date field we need to account for weekends so that we only count 2 business days. The logic is simple, if the e-mail arrives on Monday, Tuesday or Wednesday, we just add 2 days to today’s date to equal the due date. If the e-mail arrives on Thursday, Friday, or Saturday we add 4 days to account for a full weekend. And finally, if the e-mail arrives on Sunday, we add three days to account for a half weekend.

if (dtgToday.DayOfWeek == DayOfWeek.Monday
dtgToday.DayOfWeek == DayOfWeek.Tuesday
dtgToday.DayOfWeek == DayOfWeek.Wednesday)
{
ListItem["Due Date"] = dtgToday.AddDays(+2).ToShortDateString();
}
else if (dtgToday.DayOfWeek == DayOfWeek.Thursday
dtgToday.DayOfWeek == DayOfWeek.Friday
dtgToday.DayOfWeek == DayOfWeek.Saturday)
{
ListItem["Due Date"] = dtgToday.AddDays(+4).ToShortDateString();
}
else if (dtgToday.DayOfWeek == DayOfWeek.Sunday)
{
ListItem["Due Date"] = dtgToday.AddDays(+3).ToShortDateString();
}

7. Now we only have to add logic to capture attachments. We will need to instantiate two related object types for this code, a SPAttachmentCollection object to add attachments in the list and a SPEmailAttachmentCollection to extract attachments from the e-mail. Essentially we will loop through the SPAttachmentCollection object collection and for each SPEmailAttachment item in the SPAttachmentCollection create a list attachment item. I also added some logic for capturing attachments sent from Outlook. Because Outlook saves it’s attachments in a proprietary format, these files cannot be added to SharePoint list – for more information see here.

SPAttachmentCollection itemAttachments = Item.Attachments;
SPEmailAttachmentCollection emailAttachments = Message.Attachments;
foreach (SPEmailAttachment emailAttachment in emailAttachments)
{
if (emailAttachment.FileName != "winmail.dat")
{
byte[] emailAttachmentbytes = new byte[emailAttachment.ContentStream.Length];
emailAttachment.ContentStream.Read(emailAttachmentbytes, 0, (int)emailAttachmentbytes.Length);
itemAttachments.Add(emailAttachment.FileName, emailAttachmentbytes);
ListItem["Event Log"] = emailAttachment.FileName.ToString() + " : SharePoint added an attachement.";
}
else
{
ListItem["Event Log"] = emailAttachment.FileName.ToString() + " : SharePoint cannot add these types of attachements.";
}
}

8. Finally, we just add the statement to update the list item, and we are done.

ListItem.Update();

9. In my next article I’ll provide the whole code listing as well as discuss how to deploy the event handler as a feature using WSPBuilder, and also some ways to debug the feature.


I hope that helps!

Wednesday, October 6, 2010

Develop a SharePoint 2007 Event Handler (Part 2)

This is Part 2 of a multi-part article.

For Part 1 see this link - Part 1
For Part 3 see this link - Part 3
For part 4 see this link - Part 4

1. The next step is to start developing the custom event handler. For our development we will be using Visual Studio 2008 with WSPBuilder installed.

2. To create the Project follow these steps:

a. Open Visual Studio 2008

b. Create a new project of the type WSPBuilder Project, name it EmailEventHandlers

c. In Visual Studio, Right click on the project name and from the context menu choose Add -> New Item

d. From the pop-up dialogue box click on the WSPBuilder category in the left pane and choose the Event Handler Template in the right pane.

e. Name the event handler “EmailEventHandler”

f. A new pop-up menu will appear prompting you to add a Title, Description, and Scope, we will add the following information:

• Title: EmailEventHandler

• Description: A custom event handler for the e-mail received event.

• Scope: Web (Web Site or Sub Site)

g. WSPBuilder will create the correct 12-structure in the solution; it will also automatically add a reference to "Microsoft.SharePoint.dll" which is required by the event handler.

h. WSPBuilder will also automatically create the feature.xml and elements.xml with some of the tags pre-populated. We need to make a few corrections to the tags in the elements file:

• Name: EmailEventHandlers

• Type: EmailReceived

• Sequence: 20000

i. WSPBuilder also adds a class template as a starting point, and the class has the following using statements:

• using System;

• using System.Collections.Generic;

• using System.Text;

• using Microsoft.SharePoint;

j. WSPBuilder also adds some method stubs, but these are all related to the Item Add and Item Update events so we will not use them.

k. At this point, and due largely to WSPBuilder, all the initial work of project setup is already completed, and we can now proceed to the next step which is adding the remaining code framework.

3. To add the remaining code framework follow these steps:

a. Add the following using statements:

using System.Text.RegularExpressions;

using Microsoft.SharePoint.Utilities;

using Microsoft.SharePoint.Workflow;

b. Change the class inheritance from SPItemEventReceiver to SPEmailEventReceiver

c. Inside the class brackets delete the existing method signatures and add this method signature in their place:

public override void EmailReceived(SPList List, SPEmailMessage Message, string strReceiverData){ }

d. Your code so far should look as follows:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;

namespace EmailEventHandlers
{
     class EmailEventHandler : SPEmailEventReceiver
    {
        public override void EmailReceived(SPList List, SPEmailMessage Message, string strReceiverData)
       {
       }
    }
}

4. Now run build on the project, correct any errors if they occur (and hopefully they won’t) and you are now ready to begin the actual development, which will be the topic of my next Blog.

And that's all there is to it!

Tuesday, October 5, 2010

Develop a SharePoint 2007 Event Handler (Part 1)

This multi-part blog will lead you through the process of creating a custom SharePoint 2007 event handler.

For Part 1 see this link - Part 2.
For Part 2 see this link - Part 3.
For Part 4 see this link - Part 4.

1. Custom SharePoint event handlers are a powerful tool for any SharePoint solution. Essentially custom event handlers replace the default SharePoint list or library event handler behavior with more advanced and powerful behaviors. Custom event handlers add several capabilities to your list event, some of the capabilities you’ll want to explore include the following:

a. Extracting information from an e-mail sent to the list or library

b. Extracting information from another SharePoint list

c. Adding information to a SharePoint list

d. Performing calculations with SharePoint data

e. Starting a list or library workflow

2. Before you begin to design a custom event handler you will need two things a server environment, and a development environment. (To set up you own server environment see this article, and to set up your own development environment see this article). Assuming you already have these environments and they are configured as described in the articles above, let’s proceed with our development.

3. For our task we want to create a custom e-mail event handler. This e-mail event handler will allow us to task someone to answer e-mails that are sent to a SharePoint list. Basically, this event handler will create a list item in the Inbox list, calculate the due date for the response to the e-mail, and trigger a workflow that creates the response task.

4. Before we can develop we need to 1). Define functional requirements, 2). Define technical requirements, and 3). Design the solution, so let’s take it step by step. The functional requirements for our event handler are stated below:

a. When an e-mail is received create a new Inbox list item

b. Calculate the due date, which will be two business days from the date received to include accounting for weekends and holidays (holidays are determined by the Holiday list)

c. Trigger a workflow that creates the response task (task are created in the Task list)

5. The technical requirements for our event handler are stated below:

a. Create an Inbox list that is configured to receive e-mail, the structure of the e-mail list is shown below:



b. Create a Holidays list that is configure to capture holiday metadatathe structure of the e-holiday list is shown below:

c. Create a Task list that is configured to capture user tasksthe structure of the task list is shown below:



d. Create a SharePoint Designer workflow createTask that is designed to create a task in the Task list

e. Override the standard e-mail received event

f. Determine the site context

g. Capture the e-mail metadata

h. Calculate the due date using data from the Holidays list

i. Create a new list item in the Inbox list

j. Trigger the createTask workflow

6. Now using Visio we will create a very simple design, keep in mind this design is for explaining the event handler to our customers, not our fellow software engineers, so we will use the following simple block diagram:



7. Now we are all set to begin our development, which is where the next part of this article will begin.

I hope that helps, and I will write more soon!

Monday, October 4, 2010

Set Up a SharePoint 2007 Development Environment

This blog will help you set up your own SharePoint 2007 development environment.

1. To develop solutions for SharePoint 2007 you will need to install your development tools directly onto the SharePoint server. Since having development tools installed directly to the server is generally not allowed in production or even test environments you will need to build a separate development environment. By using Virtual PC 2007, you can easy to create a virtual SharePoint environment that runs on an average workstation. For more information on creating your own virtual development environment please see the article here.

2. Once you have established your development environment you will need to install and configure several development tools. The following list the set of development tools I use and, if the tools are free, I also list a download location. (I will describe how to install and use these tools later in the article.)

a. Visual Studio 2008

b. SharePoint Server 2007 SDK – Download Here

c. Visual Studio 2008 extensions for Windows SharePoint Services 3.0, v1.3 – Download Here

d. WSPBuilder – Download Here

e. Event Handler Manager – Download Here

f. Search Coder – Download Here

g. SP Log Viewer – Download Here

h. SharePoint Designer 2007 (Now a free tool!) – Download Here

i. Microsoft Visio 2007 – Visio is an optional tool, but given its usefulness for design diagrams I highly recommend it.

3. The first tool to install is Visual Studio 2008. I recommend installing the full MSDN Library with Visual Studio, it takes up a lot of additional space, but if this is your development environment there should be plenty of extra room on your hard drive. If you need help with the install there is a good Video Tutorial located here – Visual Studio Install Video. You will be prompted to choose your development environment, I choose “Visual C# Development Settings” but for SharePoint development you can also choose “Visual Basic Development Settings”. To establish that there are no issues with your Visual Studio install, and before proceeding with the rest of the steps, it’s a good idea to first create a throw away project, build it, run it, and check for configuration or install errors.

4. The next tool is the SharePoint Server 2007 SDK. The SharePoint Server 2007 SDK contains conceptual overviews, “How Do I…?” programming tasks, developer tools, code samples, references, and an Enterprise Content Management (ECM) starter kit to guide you in developing solutions based on Microsoft Office SharePoint Server 2007. The install instructions are very simple and can be found on the same page you download the SDK from. Again, to validate that the install went well, it’s best to open Visual Studio, click on Help -> Search, search for content related to the SharePoint object model, and check for configuration or install errors.

5. Now we can install Visual Studio 2008 extensions for Windows SharePoint Services 3.0 v1.3, or VSEWSS. VSEWSS provides SharePoint project and item templates for Visual Studio 2008. All things considered, the templates provided are limited, but for the most part they offer a better starting point then the out of the box Visual Studio templates. The install is very simple, and to test it I recommend that you open one or two templates, create a throw away project from it, and then check for configuration or install errors. The flowing templates are provided:

a. SharePoint Sequential Workflow

b. SharePoint State-Machine Workflow

c. Team Site Definition

d. List Definition

e. Blank Site Definition

f. Web Part

g. Empty

6. WSPBuilder is probably the best tool to become available for SharePoint development so far. WSP Builder is the invention of AnchorPoint who describes it as “A SharePoint Solution Package (WSP) creation tool for WSS 3.0 & MOSS 2007”. A more complete description is to say that WSP essentially takes the all the hard work out of creating WSP files and/or editing xml or ddf files manually. You can use WSP Builder to create the 12 “hive” structure and then add your features, web parts, receivers, etc. When you run WSPBuilder your code and artifacts get packaged into a solution file that can be passed to the SharePoint administrator for deployment. A great walk through of WSP Builder is provided by Tobias Zimmergren – you can view it here. WSP Builder is very easy to install, with Visual Studio closed, just run the MSI from your virtual environment, and once the install routine completes, open Visual Studio - WSP Builder will be installed.

7. Event Handler Manager is a special tool just for developing Event Handlers, but since most developers struggle with Event Handler debugging, this is a real must. Event Handler Manager allows the developer to browse, register and remove SharePoint event handlers. This application provides the ability to register event handlers to multiple lists at once as well as remove event handlers from multiple lists at once. This tool comes packaged as a Visual Studio project which you can then add to your project folders and run from Visual Studio.

8. Search Coder is another great tool, especially designed to help you write custom search web parts and solutions. Essentially, Search Coder allows you to connect to your SharePoint site and then try out different search queries using both the Object Model and Web Service. You can build, run and measure the performance of the query. To install just download the zip file, run install, and Search Coder will unpack to its own folder.

9. SP Log Viewer is an administrative tool not a development tool, but it is very useful to SharePoint developers. SP Log Viewer enables you to easily read and filter SharePoint log data from log files. If you have ever tried to extract useful information from the SharePoint log files you know this isn’t an easy process, and that is where SP Log Viewer can help. Again, the install is easy, just download the zip file, run the installer, and the utility will extract to its own folder.

10. SharePoint Designer (SPD) is an essential SharePoint development tools. It would take a separate article to describe everything SPD can do for the developer, but some of the main areas are site administration, trouble shooting, workflows, branding, Data View Web Part, XSL\XSLT, JavaScript and more. SharePoint Designer 2007 is now a free tool available from Microsoft, and there is an abundance of documentation available for it. The install is wizard driven and self explanatory.

11. Last but certainly not least is Microsoft Visio 2007 or 2010. In my opinion Visio is the best tool for designing SharePoint solutions and there are several great third party stencils available for SharePoint which you can purchase here. Once purchased the Visio install is wizard driven and self explanatory.

When it comes to SharePoint development, having the right tools is half the battle, armed with the tools I described in this article, you'll be well on your way to making great SharePoint 2007 solutions.