6.2. Designing a Solution

The following solutions will be used to solve the HR hiring problem, using Microsoft Office SharePoint Server 2007. Note that the tools are also available in Windows SharePoint Services 3.0.

  1. A dedicated site for the hiring process.

  2. A list of departments participating in the application.

  3. A list of jobs opening with job details and hiring managers.

  4. A list of applicants for each job and a place to attach resumes.

  5. An RSS feed for the jobs and applicants, which allows only the HR director to subscribe.

  6. An email to be delivered to the hiring manager when a new applicant is entered into the system.

Due to time constraints on the development team, this is the only functionality that will be created for this phase. Later phases will add the functionality for the interview process, but this portion of work will solve the majority of the problems the HR department is facing.

This application uses common SharePoint development approaches to solve this problem. Refer to Windows SharePoint Services 3.0 SDK and Microsoft Office SharePoint Server 2007 SDK to help answer any questions about the object model discussed.

6.2.1. Creating Dedicated Site

This project requires a dedicated site for the HR department and hiring managers to visit and use the application. For this example, create a site called Hiring Management and link it off of the main SharePoint portal for the corporation's intranet. Select the template Blank Site and URL name hiringmanagement for the new site. Review Figure 6-1 to confirm the settings used in creating the site. Use Chapters 3 and 4 to review the steps on creating a site if needed.

Figure 6.1. Figure 6-1

The navigation of the blank site is not suited for this application. By default, Documents, Lists, Discussions, Sites, and People and Groups are added as link categories. Since the application is tailored to a specific need, modify the Navigation list in Site Settings to use the categories in the following table. From the default site page, click the Site Actions button and click the Site Settings link. From there, click the Quick Launch link in the Look and Feel section. On this page, add the new headers and remove the unwanted categories.

CategoryDescription
StaffContainer for all staff related lists
JobsContainer for job and applicant lists
People and GroupsOriginal container

The next step is to edit the home page for the site. Since the blank template was chosen, this just requires you to remove the Site Image Web Part. Once this is removed, you can move on to the next step.

6.2.2. Create a Department List

Creating a list of the different departments that participate in the new hiring application gives you the flexibility to add jobs by department. The list also contains the criteria that the hiring manager needs for the department when applicants are entered.

This chapter assumes that you are familiar with creating a list. Using the site management tools, create a list named Departments. The list needs to be a Custom List; use the table below to build the required fields. After the list is created, move the Quick Launch link to the Staff category using the Navigation tools for the site.

To add columns to a custom list, click the List Setting link in the Settings menu on the list. From the Customize Departments screen, click the Create column link in the Columns section.

Note that you should change the name of the Title column to Department Name.

NameTypeDescriptionRequired
Department Name (rename Title)Single line of textName of the department that is participating in the hiring applicationYes
Hiring ManagerPerson or Group (People Only)The hiring manager of the departmentYes

Using the Active Directory or local user management features of the SharePoint installation, add three users, Bob IT, Tom HR, and Alan Sales. These will be used to fill in sample data for this application for a demo and confirmation of functionality.

To confirm that the functionality is correct, add the sample data in the following table, using the new item link of the list:

Department NameHiring Manager
Information TechnologyBob IT
SalesAlan Sales
Human ResourcesTom HR

Once the data is entered, confirm that the data is displayed in the view and move on to the next step.

6.2.3. Create a Jobs List

After the Department list is finished, create a new list for storing the jobs associated with this application. This list is used by the hiring manager to control the open positions in his or her department and by the human resources staff to associate applicants.

Using the site management tools, create a custom list named Jobs. Move this list to the Jobs category, using the Quick Launch navigation tool inside Site Settings.

Using the administration settings for the list, create the columns listed in the following table:

NameTypeDescriptionRequired
Title (default)Single line of textName of the positionYes
DepartmentLookup (Departments list, Department Name column)The department the job belongs toYes
Internal DescriptionMultiple lines of text (Rich Text)The description viewed by employees for this positionNo
External DescriptionMultiple lines of text (Plain Text)The description used by HR to broadcast the position's availabilityYes
ActiveYes/NoJob active statusN/A
Salary RangeSingle line of textDescription of expected salary rangeNo

Enter the following sample data into the Jobs list using the New Item link.

Information Technology Department Position

  • Title = Software Developer

  • Department = Information Technology

  • Internal Description = Empty

  • External Description = XYZ, Inc. is currently looking for experienced .NET developers to work on their point-of-sale application. Previous experience with C#, SQL Server, and XML is required.

  • Active = Yes

  • Salary Range = $60-70k

Sales Department Position

  • Title = Sales Team Member

  • Department = Sales

  • Internal Description = Empty

  • External Description = XYZ, Inc. is currently looking for energetic applicants for promoting their point-of-sale application. This position requires applicants with 2 years of sales experience and individuals who can rebound from rejection.

  • Active = Yes

  • Salary Range = $35-45k

Once the data is entered, confirm that the data is displayed in the view and move on to the next step.

6.2.4. Create the Applicant List

The applicant list holds information about applicants who have submitted their resumes for a particular position. If the applicant is approved after human resources' initial screening, HR will create a record in the Applicant list and attach the resume for the hiring manager to review.

In a later step, you revisit this list and associate an event receiver to email hiring managers when a new applicant is added.

Using the site management tools, create a custom list named Applicant. Move this list to the Jobs category, using the Quick Launch navigation tool inside Site Settings.

Using the administration settings for the list, create the columns listed below.

NameTypeDescriptionRequired
Applicant Name (rename Title column)Single line of textName of the applicantYes
JobLookup (Jobs list, Title column)The particular position being applied forYes
Applied DateDate and Time (Date Only)The date the applicant applied for the positionYes
Email AddressSingle line of textApplicant's email addressYes
Phone NumberSingle line of textApplicant's phone numberYes
NotesMultiple lines of text (Rich Text)Internal notes from the HR staff to inform the hiring manager of the initial review processNo

The list will use the Attach File functionality of the New Item page to post the resumes to the list.

To test the list functionality, enter the following example data. Figure 6-2 shows the example entered into the New Item page.

  • Applicant Name = John Smith

  • Job = Software Developer

  • Applied Date = <Today's Date>

  • Email Address = <Working Email Address>

  • Phone Number = (###) ###-####

  • Notes = This applicant seems extremely qualified for the position based on initial analysis. Next steps will be to review the attached resume and call him.

  • Attach File = Any PDF available of a reasonable size or example resume.

At this point, the application is functional but lacks some of the extra features added in Windows SharePoint Services 3.0 that help users be more productive by saving them time when applicants and jobs are created.

Figure 6.2. Figure 6-2

6.2.5. Create RSS Feeds

RSS, Really Simple Syndication, is an XML dialect used by subscribers so that they are alerted when content changes. Later chapters in this book cover RSS in more detail. RSS feeds are enabled by default for all lists created in SharePoint, but this application only requires it on some lists.

In the application, different team members will use Outlook 2007 to subscribe as the consumers of these RSS feeds. Unlike email, RSS uses a subscription model to retrieve content instead of a push. This means that Outlook will reload each feed it has in the feed store and look for changes from the previous version. When a new change is found, Outlook will notify the user with an unread mail flag.

The users of this application will subscribe to the RSS feeds generated from the lists based on the need of their role. Review the following table and make the appropriate changes to the application site:

List NameEnabledConsumer
DepartmentsNoDisabled
JobsYesHR Staff
ApplicantsYesHR Staff, Department Heads

To turn RSS on or off, use the RSS Settings link in the List Settings. After the page loads, select Yes or No in the List RSS section. Review Figure 6-3 to see the configuration screen.

6.2.6. Set Up Management Email

The department managers would like to receive an email when a new applicant is entered into the system. This email needs to show all the fields of the Applicant List as well as an attachment of the applicant's resume.

SharePoint list alerts would be a good candidate, but since the team wants the emails in a specific format, SharePoint event receivers will be used instead.

6.2.6.1. SharePoint Event Receivers

SharePoint generates events to notify custom code modules about significant changes, such as the addition or deletion of a list item. The SharePoint object model includes several base classes for building custom event receivers, also called event handlers. After choosing the appropriate base class and adding the custom code, you must sign and build the event receiver module and deploy it to the Global Assembly Cache (GAC) on the SharePoint server. After successful deployment, you can associate the event receiver with a site or list.

An event receiver can also be associated with a feature in SharePoint. These features should be created if the action needs to be placed on more than one list or site. Via the Site Settings, the administrator of the site can then toggle the feature on or off based on the current need.

Figure 6.3. Figure 6-3

The following table lists some event receiver base classes found in the Microsoft.SharePoint namespace.

Base ReceiverEvents
SPWebEventReceiverSiteDeleted
SiteDeleting 
WebDeleted 
WebDeleting 
WebMoved 
WebMoving 
SPListEventReceiverFieldAdded
FieldAdding 
FieldDeleted 
FieldDeleting 
FieldUpdated 
FieldUpdating 
SPItemEventReceiverItemAdded
ItemAdding 
ItemAttachmentAdded 
ItemAttachmentAdding 
ItemAttachmentDeleted 
ItemAttachmentDeleting 
ItemCheckedIn 
ItemCheckedOut 
ItemCheckingIn 
ItemCheckingOut 
ItemDeleted 
ItemDeleting 
ItemFileConverted 
ItemFileMoved 
ItemFileMoving 
ItemUncheckedOut 
ItemUncheckingOut 
ItemUpdated 
ItemUpdating 

6.2.6.2. Xyz.HumanResources Class Project

For this application, create a class library project inside Visual Studio to hold the event receiver that will be attached to the Applicant list. The receiver will send an email to the hiring manager when a new applicant is added to one of the manager's openings.

Since the default class file associated with project type is not needed, remove it. Then, associate the Microsoft.SharePoint.dll with the project through the Add New References functionality of the project. To find this assembly, use the .NET tab in the reference window and scroll to the appropriate entry.

To associate this project with the SharePoint installation, the compiled library must be added to the Global Assembly Cache. The steps to do this can be found later in this chapter. However, to prepare the assembly for the GAC, this project must be signed. If the project is recompiled after deploying to the GAC and registering to SharePoint for modifications, reset IIS on the SharePoint server to replace the assembly in the ASP.NET cache.

Signing a project is very easy to do and can be achieved by following these steps:

  1. In Solution Explorer, right-click on the project name and click Properties.

  2. On the left side of the Properties screen, click the Signing tab.

  3. Check the Sign the assembly box.

  4. From the drop-down list below the check box, select the new option.

  5. Fill in a name for the key in the Key file name text box.

  6. Associate a password with the key, and confirm it in the second box.

  7. Click the OK button.

  8. Close the Properties screen.

Compile the project and check for any errors. If no errors are found, move on to the next step.

6.2.6.3. Creating an Event Receiver

Next, create a class named ApplicantEventReceiver. The class needs to inherit from SPItemEventReceiver as it will attach to the ItemAdded event of the Applicants list. Due to the amount of objects this project uses in the Microsoft.SharePoint namespace, declare the namespace with the C# using statement.

Using the IntelliSense inside Visual Studio 2005, type override and select the ItemAdded method from the list. Visual Studio will then stub out the method, and it will resemble the following:

public override void ItemAdded(SPItemEventProperties properties)
{

}

When you attach this event receiver to a list, SharePoint calls the ItemAdded method whenever a user adds a new item to that list. The event handler then receives the new item as a property collection. This parameter will be very significant for our event receiver.

The next step is to create a method for loading the SmtpClient in System.Net.Mail named LoadSmtpInformation. This method does not require any parameters and will return the SmtpClient object created inside of it. Notice that mail is not handled in .NET 2.0 as it was in .NET 1.x. Developers should review the documentation with .NET 2.0 to become more familiar with this namespace if it is new to them.

After creating the method, add the code to identify the SMTP server information for passing mail through. Due to security issues, adding credentials for the SMTP server may be required. Once completed the method should resemble the following:

private SmtpClient LoadSmtpInformation()
{
    SmtpClient client = new SmtpClient();

    client.Host = "server address";
    client.Port = 25;
    client.Credentials = new NetworkCredential("username", "password");

    return client;
}

To continue, create the BuildEmailBody method, which constructs the message that will be sent to the hiring manager. This method receives the event property list and returns an HTML string.

The method should be similar to the following method, but does not need to be exact:

private string BuildEmailBody(SPListItem item)
{
    StringBuilder body = new StringBuilder();

    body.Append("This email has been automatically sent from the Hiring Management system. <br /><br />");
    body.Append("<table border="0" cellpadding="2"
cellspacing="0">");
    body.Append("<colgroup><col width="150" align="right" /><col width="350" /></colgroup>");
    body.AppendFormat("
<tr><td>Applicant Name:<td><td>{0}<td></tr>", item["Applicant Name"]);

    SPFieldLookupValue jobValue = (SPFieldLookupValue)item.Fields["Job"].GetFieldValue((string)item["Job"]);
    body.AppendFormat("
<tr><td>Job:<td><td>{0}<td></tr>", jobValue.LookupValue);

    body.AppendFormat("
<tr><td>Applied Date:<td><td>{0}<td></tr>", item["Applied Date"]);
    body.AppendFormat("
<tr><td>Email Address:<td><td>{0}<td></tr>", item["Email Address"]);
    body.AppendFormat("
<tr><td>Phone Number:<td><td>{0}<td></tr>", item["Phone Number"]);
    body.AppendFormat("
<tr><td>Notes:<td><td>{0}<td></tr>", item["Notes"]);
    body.Append("</table>");

    return body.ToString();
}

Notice that this method uses the item to pull out the different fields added by the end user. The syntax item["fieldname"] will return the object equivalent of the field used. Since most of these fields are strings, you can append them to the StringBuilder without any formatting concerns.

However, the Job field is a lookup on the Jobs list to provide a link back to the job and, beyond that, to the department and hiring manager.

There are two approaches to pulling the display value for this field. If you insert the property item directly like the other fields, SharePoint will return a string with the ID and value, separated by a semicolon and number sign. An example is "1;#Software Developer" for the first job created. A better approach, shown above, casts the Job property to its true type, which is SPFieldLookupValue. Then you call its LookupValue method to obtain the default text, which is the job name.

The next step is to create the LoadHiringManagersEmail method to fetch the hiring manager's email address. This method uses the lookup techniques described above to find the appropriate email address. You need to navigate through the Job list and Department list to find the Hiring Manager information, as shown in the following code sample:

private string LoadHiringManagersEmail(SPListItem item)
{
    SPList jobList = item.ParentList.ParentWeb.Lists["Jobs"];
    SPFieldLookupValue jobValue = (SPFieldLookupValue)item.Fields["Job"].GetFieldValue((string)item["Job"]);
    SPItem jobItem = jobList.Items[jobValue.LookupId];

    SPList departmentList = jobList.ParentWeb.Lists["Departments"];
    SPFieldLookupValue departmentValue = (SPFieldLookupValue)jobItem.Fields["Department"].GetFieldValue((string)jobItem["Department"]);
    SPItem departmentItem = departmentList.Items[departmentValue.LookupId];

    SPFieldUserValue hiringManager = (SPFieldUserValue)departmentItem.Fields["Hiring Manager"].
GetFieldValue((string)departmentItem["Hiring Manager"]);

    return hiringManager.User.Email;
}

Notice that this example navigates through the list and uses a new value object to pull the user information named SPFieldUserValue. This object is utilized by fields that use the SharePoint list item type for user lookup. The property User includes a property named Email as well as many other key fields for identifying the user.

Now pull the previous two methods together by creating a BuildMailMessage method that will call them and build the MailMessage for sending through the SmtpClient. This method will accept the list passed through the ItemAdded event and return a MailMessage object. This message object will also need to include the attachments of the applicant list as email attachments. This can be achieved by using the Attachments list inside the list item object. Once finalized, the method should be close to the following:

private MailMessage BuildMailMessage(SPListItem item)
{
    MailMessage message = new MailMessage();

SPList list = item.ParentList;

    message.From = new MailAddress("[email protected]");
    message.To.Add(new MailAddress(LoadHiringManagersEmail(item)));

    message.IsBodyHtml = true;
    message.Body = BuildEmailBody(item);
    message.Subject = "Hiring Management - Applicant Created";

    for (int attachmentIndex = 0; attachmentIndex < item.Attachments.Count; attachmentIndex++)
    {
        string url = item.Attachments.UrlPrefix + item.Attachments[attachmentIndex];
        SPFile file = list.ParentWeb.GetFile(url);

        message.Attachments.Add(new Attachment(file.OpenBinaryStream(), file.Name));
    }

    return message;
}

The final logic needed for this event receiver is to call the SMTP object builder and call the last method you created. To do this, add the following lines of code to the ItemAdded method created in the first step of this class:

SPListItem item = properties.ListItem;
SmtpClient client = LoadSmtpInformation();

client.Send(BuildMailMessage(item));

Now, compile the code and repeat until no errors are found. The next steps will be to deploy the assembly to the SharePoint server and attach the event receiver to the applicant list.

The final code for the event receiver should be close to the following:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Mail;

using Microsoft.SharePoint;

namespace Xyz.HumanResources
{
    public class ApplicantEventReceiver : SPItemEventReceiver
    {
        public override void ItemAdded(SPItemEventProperties properties)
        {
            SPListItem item = properties.ListItem;
            SmtpClient client = LoadSmtpInformation();

client.Send(BuildMailMessage(item));
        }

        private SmtpClient LoadSmtpInformation()
        {
            SmtpClient client = new SmtpClient();

            client.Host = "mail.geekswithblogs.com";
            client.Port = 25;
            client.Credentials = new System.Net.NetworkCredential("[email protected]", "erjiiu");

            return client;
        }

        private string BuildEmailBody(SPListItem item)
        {
            StringBuilder body = new StringBuilder();

            body.Append("This email has been automatically sent from the Hiring Management system. <br /><br />");
            body.Append("<table border="0" cellpadding="2" cellspacing="0">");
            body.Append("<colgroup><col width="150" align="right" /><col width="350" /></colgroup>");
            body.AppendFormat("
<tr><td>Applicant Name:<td><td>{0}<td></tr>", item["Applicant Name"]);

            SPFieldLookupValue jobValue = (SPFieldLookupValue)item.Fields["Job"].GetFieldValue((string)item["Job"]);
            body.AppendFormat("
<tr><td>Job:<td><td>{0}<td></tr>", jobValue.LookupValue);

            body.AppendFormat("
<tr><td>Applied Date:<td><td>{0}<td></tr>", item["Applied Date"]);
            body.AppendFormat("
<tr><td>Email Address:<td><td>{0}<td></tr>", item["Email Address"]);
            body.AppendFormat("
<tr><td>Phone Number:<td><td>{0}<td></tr>", item["Phone Number"]);
            body.AppendFormat("
<tr><td>Notes:<td><td>{0}<td></tr>", item["Notes"]);
            body.Append("</table>");

            return body.ToString();

        }

        private MailMessage BuildMailMessage(SPListItem item)
        {
            MailMessage message = new MailMessage();
            SPList list = item.ParentList;

            message.From = new MailAddress("[email protected]");
            message.To.Add(new MailAddress(LoadHiringManagersEmail(item)));

message.IsBodyHtml = true;
            message.Body = BuildEmailBody(item);
            message.Subject = "Hiring Management - Applicant Created";

            for (int attachmentIndex = 0; attachmentIndex < item.Attachments.Count; attachmentIndex++)
            {
                string url = item.Attachments.UrlPrefix + item.Attachments[attachmentIndex];
                SPFile file = list.ParentWeb.GetFile(url);

                message.Attachments.Add(new Attachment(file.OpenBinaryStream(), file.Name));
            }

            return message;
        }

        private string LoadHiringManagersEmail(SPListItem item)
        {
            SPList jobList = item.ParentList.ParentWeb.Lists["Jobs"];
            SPFieldLookupValue jobValue = (SPFieldLookupValue)item.Fields["Job"].GetFieldValue((string)item["Job"]);
            SPItem jobItem = jobList.Items[jobValue.LookupId];

            SPList departmentList = jobList.ParentWeb.Lists["Departments"];
            SPFieldLookupValue departmentValue = (SPFieldLookupValue)jobItem.Fields["Department"].GetFieldValue((string)jobItem["Department"]);
            SPItem departmentItem = departmentList.Items[departmentValue.LookupId];

            SPFieldUserValue hiringManager = (SPFieldUserValue)departmentItem.Fields["Hiring Manager"].GetFieldValue((string)departmentItem["Hiring Manager"]);

            return hiringManager.User.Email;
        }
    }
}

6.2.6.4. Deploying an Event Receiver

You could deploy this event handler by wrapping it within a SharePoint feature package, which would make is available for reuse in other lists. This would be an excellent approach if you had built a general-purpose event handler to produce email messages based on a parameterized template. As you gain SharePoint development skills, you might want to tackle that challenge.

However, the version implemented above is very specific to this hiring process example, so you want to restrict its use to that scenario. To accomplish this type of restricted deployment, you can build a console application that deploys the event handler by invoking the SharePoint object model. This approach has the added advantage of enabling you to update the event handler simply by replacing the assembly in the GAC and recycling IIS.

First, use Visual Studio to create a console application. In the Main method, create a SPSite object to access the hiring management site. Next, create an SPWeb object and assign it to the OpenWeb method on the site object. This object will allow the user to find the applicant list on the SharePoint server.

After opening the web object, load the applicant list using the Lists property. On the list, find the EventReceivers collection and use the Add method to pass the appropriate fields that identify the assembly containing the receiver and the receiver class itself. Some of the values needed to build the type string can be retrieved from the GAC tools provided in the .NET SDK.

Once the receiver is associated with the list, write a completed message to the console and prompt the user for input so that the application does not close before the user can ensure that the application was successful.

This method should look similar to the example here:

static void Main(string[] args)
{
    SPSite site = new SPSite("http://server/hiringmanagement/");
    SPWeb web = site.OpenWeb();
    SPList list = web.Lists["Applicant"];

    string assemblyName = "Xyz.HumanResources, Version=1.0.0.0, Culture=neutral,PublicKeyToken=TOKEN";
    string className = "Xyz.HumanResources.ApplicantEventReceiver";

    list.EventReceivers.Add(SPEventReceiverType.ItemAdded, assemblyName, className);

    Console.WriteLine("-- Registered --");
    Console.Read();
}

To confirm that the receiver was registered correctly, add an applicant to one of the jobs created early and check the email of the hiring manager that the job was associated with. Make sure that the test includes sample resume attachments, to review the complete functionality.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.231.52