Search This Blog

Showing posts with label Event Handler. Show all posts
Showing posts with label Event Handler. Show all posts

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!