custom workflow activities

57
Creating Custom Workflow Activities for SharePoint Server 2007 Using Visual Studio 2008 Summary: Learn how to create a custom activity for Microsoft Office SharePoint Server 2007 to send an e-mail message that has an attachment. Applies to: Microsoft Office SharePoint Server 2007, Microsoft Visual Studio 2008 Mike Rand, 3Sharp June 2008 In Microsoft Visual Studio 2008, you can create custom activities that can be consumed in workflows. Creating custom activities lets you encapsulate business logic that applies to different scenarios and that can be used in different workflows. This Microsoft Office Visual How To demonstrates how to create a custom activity to send an e-mail message with an attachment. First, you must create your custom activity. Then, you can add that to a workflow project and use it to send an e-mail message with an attachment. Creating a Custom Activity Project First, create a Visual Studio 2008 Workflow Activity Library project. To create a Visual Studio 2008 Workflow Activity Library project 1. Open Visual Studio 2008. 2. On the File menu, point to New, and then click Project. 3. Under the Workflow Project Type, select the Workflow Activity Library project template. 4. In the Name box, type SendMailWithAttachmentActivity, and then click OK. 5. Rename Activity1 to SendMailWithAttachmentActivity. Coding Custom Activity Now that you have a Custom Activity project, you must add code to send an e-mail message with an attachment. To add code to send an e-mail message with an attachment 1. The first thing you must do is change your class declaration to inherit directly from Activity instead of SequenceActivity. Open your activity in code view, and change SequenceActivity to Activity. Your class definition should look like the following. C# Copy Code public partial class SendMailWithAttachmentActivity : Activity

Upload: semalaiappan

Post on 12-Nov-2014

2.650 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Custom Workflow Activities

Creating Custom Workflow Activities for SharePoint Server 2007 Using Visual Studio 2008Summary: Learn how to create a custom activity for Microsoft Office SharePoint Server 2007 to send an e-mail

message that has an attachment.

Applies to: Microsoft Office SharePoint Server 2007, Microsoft Visual Studio 2008

Mike Rand, 3Sharp

June 2008

In Microsoft Visual Studio 2008, you can create custom activities that can be consumed in workflows. Creating custom activities lets you encapsulate business logic that applies to different scenarios and that can be used in different workflows. This Microsoft Office Visual How To demonstrates how to create a custom activity to send an e-mail message with an attachment.

First, you must create your custom activity. Then, you can add that to a workflow project and use it to send an e-mail message with an attachment.Creating a Custom Activity ProjectFirst, create a Visual Studio 2008 Workflow Activity Library project.To create a Visual Studio 2008 Workflow Activity Library project

1. Open Visual Studio 2008.

2. On the File menu, point to New, and then click Project.

3. Under the Workflow Project Type, select the Workflow Activity Library project template.

4. In the Name box, type SendMailWithAttachmentActivity, and then click OK.

5. Rename Activity1 to SendMailWithAttachmentActivity.

Coding Custom ActivityNow that you have a Custom Activity project, you must add code to send an e-mail message with an attachment.To add code to send an e-mail message with an attachment

1. The first thing you must do is change your class declaration to inherit directly from Activity

instead of SequenceActivity.

Open your activity in code view, and change SequenceActivity to Activity. Your class

definition should look like the following.

C#

Copy Code

public partial class SendMailWithAttachmentActivity : Activity

{ …

2. Now you must create some Dependency Properties. Add the following fields inside your class

definition.

C#

Copy Code

Page 2: Custom Workflow Activities

public static DependencyProperty ToProperty

= DependencyProperty.Register(

"To", typeof(string),

typeof(SendMailWithAttachmentsTest));

public static DependencyProperty FromProperty

= DependencyProperty.Register(

"From", typeof(string),

typeof(SendMailWithAttachmentsTest));

public static DependencyProperty CCProperty

= DependencyProperty.Register(

"CC", typeof(string),

typeof(SendMailWithAttachmentsTest));

public static DependencyProperty SubjectProperty

= DependencyProperty.Register(

"Subject", typeof(string),

typeof(SendMailWithAttachmentsTest));

public static DependencyProperty BodyProperty

= DependencyProperty.Register(

"Body", typeof(string),

typeof(SendMailWithAttachmentsTest));

public static DependencyProperty AttachmentProperty

= DependencyProperty.Register(

"Attachment", typeof(string),

typeof(SendMailWithAttachmentsTest));

public static DependencyProperty SmtpServerProperty

= DependencyProperty.Register(

"SmtpServer", typeof(string),

typeof(SendMailWithAttachmentsTest));

public static DependencyProperty InvokeEvent

= DependencyProperty.Register(

"Invoke", typeof(EventHandler),

typeof(SendMailWithAttachmentsTest));

Notice that the last field, InvokeEvent, is of type EventHandler. This enables you to add

Page 3: Custom Workflow Activities

custom code to your activity when it is used in a workflow.

3. Now, you must add properties for your fields. Add the following code under the fields you just

added.

C#

Copy Code

[DesignerSerializationVisibility(DesignerSerializationVisibility.Vis

ible)]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[Description("Enter any e-mail recipients, separated by

semicolons")]

public string To

{

get { return ((string)

(base.GetValue(SendMailWithAttachmentsTest.ToProperty))); }

set { base.SetValue(SendMailWithAttachmentsTest.ToProperty,

value); }

}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Vis

ible)]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[Description("Enter the e-mail sender")]

public string From

{

get { return ((string)

(base.GetValue(SendMailWithAttachmentsTest.FromProperty))); }

set {

base.SetValue(SendMailWithAttachmentsTest.FromProperty, value); }

}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Vis

ible)]

[ValidationOption(ValidationOption.Optional)]

Page 4: Custom Workflow Activities

[Browsable(true)]

[Description("Enter any carbon copy recipients, separated by

semicolons")]

public string CC

{

get { return ((string)

(base.GetValue(SendMailWithAttachmentsTest.CCProperty))); }

set { base.SetValue(SendMailWithAttachmentsTest.CCProperty,

value); }

}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Vis

ible)]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[Description("Enter the e-mail subject")]

public string Subject

{

get { return ((string)

(base.GetValue(SendMailWithAttachmentsTest.SubjectProperty))); }

set {

base.SetValue(SendMailWithAttachmentsTest.SubjectProperty, value); }

}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Vis

ible)]

[ValidationOption(ValidationOption.Optional)]

[Browsable(true)]

[Description("Enter the body text of the e-mail")]

public string Body

{

get { return ((string)

(base.GetValue(SendMailWithAttachmentsTest.BodyProperty))); }

set {

base.SetValue(SendMailWithAttachmentsTest.BodyProperty, value); }

}

Page 5: Custom Workflow Activities

[DesignerSerializationVisibility(DesignerSerializationVisibility.Vis

ible)]

[ValidationOption(ValidationOption.Optional)]

[Browsable(true)]

[Description("Enter an attachment file path")]

public string Attachment

{

get { return ((string)(base.GetValue

(SendMailWithAttachmentsTest.AttachmentProperty))); }

set {

base.SetValue(SendMailWithAttachmentsTest.AttachmentProperty,

value); }

}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Vis

ible)]

[ValidationOption(ValidationOption.Required)]

[Browsable(true)]

[Description("Enter the Smtp Server for the email")]

[DisplayName("Smtp Server")]

public string SmtpServer

{

get { return ((string)(base.GetValue

(SendMailWithAttachmentsTest.SmtpServerProperty))); }

set {

base.SetValue(SendMailWithAttachmentsTest.SmtpServerProperty,

value); }

}

4. Now, you must add a property for your InvokeEvent field. This EventHandler property lets

you add code in a workflow to interact with this activity programmatically. Add this code under

the Properties you just added.

C#

Copy Code

[DescriptionAttribute("Invoke")]

[CategoryAttribute("Invoke Category")]

[BrowsableAttribute(true)]

[DesignerSerializationVisibilityAttribute(DesignerSerializationVisib

Page 6: Custom Workflow Activities

ility.Visible)]

public event EventHandler Invoke

{

add

{

base.AddHandler(SendMailWithAttachmentsTest.InvokeEvent,

value);

}

remove

{

base.RemoveHandler(SendMailWithAttachmentsTest.InvokeEvent,

value);

}

}

5. Add a using statement at the top of the class. This enables you to access the ASP.NET 2.0 Mail

namespace for sending your e-mail message. Add the following code.

C#

Copy Code

using System.Net.Mail;

6. The last thing you must do here is override the Execute method. Add the following method

inside your class definition.

C#

Copy Code

Protected override ActivityExecutionStatus

Execute(ActivityExecutionContext executionContext)

{

// Raise Invoke Event to execute custom code in the

workflow.

this.RaiseEvent(SendMailWithAttachmentsTest.InvokeEvent,

this, EventArgs.Empty);

// Set reference to Smtp Server.

SmtpClient smtp = new SmtpClient(SmtpServer);

// Create mail message.

MailMessage msg = new MailMessage();

msg.To.Add(To);

Page 7: Custom Workflow Activities

msg.From = new MailAddress(From);

if (!String.IsNullOrEmpty(CC))

{

msg.CC.Add(CC);

}

if (!String.IsNullOrEmpty(Subject))

{

msg.Subject = Subject;

}

if (!String.IsNullOrEmpty(Body))

{

msg.Body = Body;

}

if (!String.IsNullOrEmpty(Attachment))

{

msg.Attachments.Add(new Attachment(Attachment));

}

// Send the e-mail.

smtp.Send(msg);

// Indicate that the activity has completed.

return ActivityExecutionStatus.Closed;

}

Installing a Custom ActivityBefore you can use your custom activity, you must install it in the global assembly cache (GAC). For an assembly to be installed in the GAC, you must give it a strong name.To install the custom activity to the GAC

1. First, give your assembly a strong name. In Solution Explorer, right-click the project, and

then select Properties.

2. Select the Signing tab.

3. Select the Sign the assembly check box.

4. In the Choose a strong name key file list, select New.

5. In the Key file name text box, type Key.

6. In this demonstration, we are not concerned with security, so clear the Protect my key file

with a password check box. Click OK.

Now your assembly is strong named, and all you have to do is install it to the global assembly

cache.

7. Save and build the project.

8. Open a Visual Studio 2008 command prompt.

9. Navigate to the Activity solution directory, and run the following command:

gacutil /if SendMailWithAttachmentActivity.dll

Now, that you have successfully installed your activity, you can use it from a workflow project.Creating a Workflow Project

Page 8: Custom Workflow Activities

Next, you create a Sequential Workflow project to use your custom activity.To create a Visual Studio 2008 Sequential Workflow project

1. Start Visual Studio 2008.

2. On the File menu, point to New, and then click Project.

3. Under the Office Project Type, select the SharePoint 2007 Sequential Workflow project

template.

4. In the Name box, type SendEmailWithAttachmentWF. Click OK.

5. Type a valid SharePoint Web URL. The example uses http://moss.litware.com. Click

Next.

6. Select a library or list to associate with your workflow, and click Next.

7. Leave the default options for how a workflow can be started, Manually by users and When

an Item is created. Click Finish.

Adding a Custom Activity to the ToolboxNow that you have created your Sequential Workflow project, you must add your custom activity to your Toolbox before you can use it.To add the custom activity to the Visual Studio 2008 Toolbox

1. On the Tools menu, select Toolbox items.

2. Select the Activities tab.

3. Click Browse, and browse to the SendMailWithAttachmentActivity.dll in your Activity solution

directory. Click Open.

4. Click OK.

5. Your activity is now available in the Toolbox.

Figure 1. Toolbox with new activity available

Note:

If you have a toolbox category selected, the activity is added to that category by default. You

can drag the activity to another category if you want.

Adding a Custom Activity to the WorkflowNow, you must add your custom activity to your simple workflow.To add the custom activity to the workflow

1. From the Toolbox, drag the SendMailWithAttachmentActivity to be under the

onWorkflowActivated1 activity.

2. Open the Properties window, and rename it to sendMailWithAttachmentActivity.

3. You can set the activity properties from within the Properties window. Instead, you will do that

in code. Select the Event view in the Properties window.

Page 9: Custom Workflow Activities

4. You should see a single event, Invoke. Double-click this property.

Figure 2. Properties window

This takes you to the code-behind class, and you will see that a method stub has been auto-

generated for you.

5. Add the following code inside this method.

C#

Copy Code

SendMailWithAttachmentActivity.To = "[email protected]";

SendMailWithAttachmentActivity.From = "[email protected]";

SendMailWithAttachmentActivity.CC = "[email protected]";

SendMailWithAttachmentActivity.Subject = "Email with Attachment

Testing.";

SendMailWithAttachmentActivity.Body = "This email should have an

attachment.";

SendMailWithAttachmentActivity.Attachment

= @"C:\Documents and Settings\Administrator\Desktop\code

snippets.txt";

SendMailWithAttachmentActivity.SmtpServer =

workflowProperties.Site.WebApplication.OutboundMailServiceInstance.S

erver.Address;

6.

Note:

The purpose of this demonstration is to show you how to create and consume a custom activity. In a real-world scenario, you would never hard-code these values. You would retrieve them programmatically, or possibly through an Initiation form or a Task form. Running the Workflow Project from Visual Studio 2008Press F5 to run your workflow. When you activate this workflow on a document in a document library, an e-mail message is generated and sent with the attachment you specified. Figure 3. E-mail message with attachment

Page 10: Custom Workflow Activities

1. Introducing Office SharePoint Designer 2007 WorkflowsOffice SharePoint Designer 2007, a replacement for FrontPage, is used as an aid in the

rapid design and deployment of workflows. Office SharePoint Designer 2007 is specifically

designed to help create and customize web sites and workflows built with SharePoint

Products and Technologies. The Development process in SharePoint Designer is based on

declarative rules-based, code-free workflow editor.

SharePoint Designer (SPD) gives list administrators, business administrators, and designers

the ability to create workflows without writing any code. SPD exposes many of the

workflow activities that ship with SharePoint as "actions" that users can string together

into a sequential process. These actions are customized via sentences that describe the

action and bind data to action parameters.

However, businesses will oftentimes need more custom functionality than the actions

provided with SharePoint, requiring them to write custom code that can run on the

server. This guide describes how to write a custom code as an activity using the Visual

Studio Extensions for Windows Workflow Foundation and expose it as an action in SPD.

"Activity" refers to the basic building block of functionality in a Windows Workflow

Foundation (WF) workflow.

Page 11: Custom Workflow Activities

In Office SharePoint Designer 2007, however, each activity appears as an action,

represented by a sentence that contains variables that the user can configure using

drop-down menus and lookup dialog boxes. Users can also select conditions, which are

configurable conditional clauses that direct the flow of the workflow.

As the user is selecting and configuring conditions and actions in the workflow interface,

Office SharePoint Designer 2007 generates the two files that actually represent the

workflow class:

The workflow markup file, which contains markup language that describes the activities

included in the workflow.

The workflow rules file contains the business logic of the workflow in declarative rules

form, rather than as code.

Page 12: Custom Workflow Activities

2. Create a Microsoft Office InfoPath 2007 Form

1. Create a new Microsoft Office InfoPath 2007 Form.

2. Add two Text boxes and rename the text boxes as "Contributors" and "Readers".

3. Save the Form.

4. Publish the form with the two columns to the Microsoft Office SharePoint Server

2007 site for which the item level security needs to be implemented.

3. Create a custom activity in Visual Studio with promoted properties

1. Navigate to Start | All Programs | Microsoft Visual Studio 2005 | Microsoft Visual

Studio 2005.

2. Select the File | New | Project menu command.

3. Visual Studio displays the New Project dialog box.

4. Select the Visual C# | Workflow project type.

5. Select the Workflow Activity Library template.

6. Enter the path in the Location field.

7. Enter the name in the Name field.

8. Click OK.

9. Visual Studio creates the activity library project, including a single activity,

Activity1, and displays a design view of Activity1.cs.

10. Rename Activity1.cs to ItemLevelSecurityActivity.cs by right clicking on Activity1.cs

and choosing rename.

11. Select the View | Toolbox menu command to open the Toolbox window.

Page 13: Custom Workflow Activities

12. From the Toolbox window, drag a Code activity and drop it onto the "Drop

Activities Here" work area of ItemLevelSecurityActivity's design view.

13. The Activity Designer displays a code icon in the work area.

14. Rename CodeActivity1 to ItemLevelSecuritycodeActivity by right clicking on

CodeActivity1 and choosing Properties and change the Name Property.

15. In the Solution Explorer, right click on References to bring up the context menu

16. Select Add Reference.

17. From the Add Reference dialog box, add references to the Windows SharePoint

Services and the Windows SharePoint Services WorkflowActions.

18. In the Solution Explorer, right click on ItemLevelSecurityActivity.cs to bring up

the context menu.

19. Select View Code.

20. Add the following namespaces in the code:

Collapse Copy Codeusing Microsoft.SharePoint;

using Microsoft.SharePoint.Workflow;

using Microsoft.SharePoint.WorkflowActions;

Page 14: Custom Workflow Activities

Note: The activity wouldn't be useful if it didn't pass information on, so to make it

available to the rest of the workflow, we will need to use property promotion. Property

promotion consists of getters and setters to allow the property to be bound to variables

outside of the activity. For this example, we need to derive the Workflow Context object

to retrieve the current SharePoint Site, the List Id for which the activity is attached and

the current List Item to provide Item Level Security.

21. Place the cursor on the closing bracket of the ItemLevelSecurityActivity

constructor

and press Enter Twice.

22. Right Click on the last line you just inserted.

23. Select Insert Snippet.

Page 15: Custom Workflow Activities

24. Select Workflow.

25. Select DependencyProperty - Property.

This code snippet generates the getter/setter code and allows you to specify the

property name, type and description for the property.

Page 16: Custom Workflow Activities

26. Fill in these fields in the boilerplate code with the corresponding values. Use Tab to

move between the fields and press enter when finished with the fields.

a. For deriving the Workflow Context object to retrieve the current SharePoint

Site:

i. Name: __Context.

ii. Type: WorkflowContext.

iii. Description: Context.

b. For retrieving the List Id for which the activity is attached:

i. Name: ListId

ii. Type: string

iii. Description: List Id

c. For retrieving the current List Item to provide Item Level Security:

i. Name: ListItem

ii. Type: int

iii. Description: ListItem

Note: Remove the Category Property and add the following code in its place for all the

three dependency properties.

[ValidationOption(ValidationOption.Required)]

The resulting output should resemble the following:

Page 17: Custom Workflow Activities

With this customized, the property is exposed to the rest of the workflow. The

workflow can now bind variables to these properties for both input and output.

27. In the Solution Explorer, right click on References to bring up the context menu

28. Select Add Reference.

29. From the Add Reference dialog box, add references to the

System.DirectoryServices.

30. In the Solution Explorer, right click on ItemLevelSecurityActivity.cs to bring up

the context menu.

Page 18: Custom Workflow Activities

31. Select View Code.

32. Add the following namespaces in the code:

Collapse Copy Codeusing System.DirectoryServices;

33. In the Solution Explorer, right click on ItemLevelSecurityActivity.cs to bring up

the context menu.

34. Select View Designer

35. Double click the ItemLevelSecuritycodeActivity activity to view the

ItemLevelSecuritycodeActivity _ExecuteCode method and write the custom

code behind your activity for implementing the Item Level Security as displayed.

Page 19: Custom Workflow Activities

36. In the Solution Explorer, Right Click on Properties and choose Open from the

context menu.

37. Navigate to the Signing tab.

Page 20: Custom Workflow Activities

38. Check the Option Sign the Assembly.

39. Select the New option from the Drop down below

40. In the Create Strong Name Key dialog box, enter the Key File Name

41. Uncheck the Protect my key file with a password option.

42. Select the Build | Build Solution menu command.

4. Deploy the dll to the GAC and add it to the web.config fileThe next step is to compile your activity and deploy it to the GAC

(C:\WINDOWS\assembly). The assembly must be signed. You can drag and drop this into

the GAC directory or use the .net gacutil tool. Keep a note of the assembly, class,

version, and public key token, as they'll be used later on in the .ACTIONS file.

1. Navigate to the root port directory of the SharePoint Site for which the activity is

created located in "C:\inetpub\wwwroot\wss\virtualdirectories" and search for

"web.config" file. These xml files contain lists of authorized types that can be used

for that server port.

2. Open the file and search for "WorkflowActions", which should take you to an entry

that looks like this:

Collapse Copy Code<authorizedType

Assembly="Microsoft.SharePoint.WorkflowActions, Version=12.0.0.0,

Culture=neutral, PublicKeyToken=71e9bce111e9429c"

Namespace="Microsoft.SharePoint.WorkflowActions"

TypeName="*"

Authorized="True" />

Underneath this tag, add a corresponding tag for your dll. For example:

Collapse Copy Code

<authorizedType

Assembly="ItemLevelSecurityActivity, Version=1.0.0.0,

Culture=neutral, PublicKeyToken=7211fc0c4fbd8603"

Namespace="ItemLevelSecurityActivityLibrary"

TypeName="*"

Authorized="True" />

The activity dll is now ready to be run on the server

Page 21: Custom Workflow Activities

5. Edit the WSS.ACTIONS file to describe the activityparametersThe final step of preparing an activity for SPD is to change the WSS.ACTIONS file. This

xml file describes the types of the promoted properties of the activity and how to map

them into a rules sentence.

1. Navigate to "C:\Program Files\Common Files\Microsoft Shared\web server

extensions\12\TEMPLATE\1033\Workflow" folder and open the WSS.ACTIONS file.

2. Navigate to the end of the file.

3. Append the following code before the </Actions> tag.

Collapse Copy Code<Action

Name="Item Level Security activity in sharepoint designer"

ClassName="ItemLevelSecurityActivityLibrary.ItemLevelSecurityActivity"

Assembly="ItemLevelSecurityActivity, Version=1.0.0.0,

Culture=neutral, PublicKeyToken=7211fc0c4fbd8603"

AppliesTo="all"

Category="Extras">

<RuleDesigner Sentence="Apply security to %1 Document Library">

<FieldBind

Field="ListId,ListItem"

Text="this"

Id="1"

DesignerType="ChooseDoclibItem" />

</RuleDesigner>

<Parameters>

<Parameter

Name="__Context"

Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext,

Microsoft.SharePoint.WorkflowActions"

Direction="In"/>

<Parameter

Name="ListId"

Type="System.String, mscorlib"

Direction="In" />

<Parameter

Name="ListItem"

Type="System.Int32, mscorlib"

Page 22: Custom Workflow Activities

Direction="In" />

</Parameters>

</Action>

Note:

The "Action" tag defines basic information about the action with the following attributes:

� Name � name of the action (this is what SPD displays in its actions list)

� ClassName � the name of the activity, i.e. Namespace.WorkflowClassName

� Assembly � details of the GAC'ed assembly

� AppliesTo � describes what types of lists this activity can be used for, either "list",

"doclib", or "all"

� Category � category that SPD will display in the categories for available actions

RuleDesigner

Collapse Copy Code

<RuleDesigner Sentence="Apply security to %1 Document Library ">

<FieldBind

Field="ListId,ListItem"

Text="this list"

Id="1"

DesignerType="ChooseDoclibItem" />

</RuleDesigner>

The next section is the "RuleDesigner" section. This describes a rule sentence for the

action as well as how to bind them to the activity properties. These are the sentences

SPD displays in its rules wizard.

The variable parameters in the sentence, e.g. %1, etc., are exposed as customization

links. When displayed, they will be replaced with the "FieldBind" tags below, where %1 will

be replaced with the FieldBind with Id=1,etc.

The "FieldBind" tag describes each variable parameter. The "Field" attribute corresponds

to the parameter, or activity property, as it is described in the Parameter tag in the

markup. "DesignerType" describes what type of interface to show when the user clicks on

Page 23: Custom Workflow Activities

the link. For example, if you want to show a select user dialog, you would use

"SinglePerson" for the designer type. The "Text" attribute is how the field is displayed in

the sentence.

The end result for the above markup would look something like this in SPD:

Parameters

Collapse Copy Code

<Parameters>

<Parameter

Name="__Context"

Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext,

Microsoft.SharePoint.WorkflowActions"

Direction="In"/>

<Parameter

Name="ListId"

Type="System.String, mscorlib"

Direction="In" />

<Parameter

Name="ListItem"

Type="System.Int32, mscorlib"

Direction="In" />

</Parameters>

Finally, the "Parameters" tag tells the RuleDesigner how to map the fields to the promoted

properties on the workflow activity.

Each "Parameter" describes the name of the property (which should match the

corresponding FieldBind above), the system type of the property, and direction ("In"

means that the activity gets that parameter, and "Out" means the activity sets that

parameter).

Once you have this file laid out, save your file.

6. Boot SPD

1. Do an iisreset.

Page 24: Custom Workflow Activities

2. Navigate to Start | All Programs | Microsoft Office | Microsoft Office

SharePoint Designer 2007.

3. Select the File | New | Workflow menu command.

4. In the Workflow Designer dialog box, enter a name for the Workflow and select

the SharePoint Document library list for which the activity should be attached from

the Dropdown.

5. Check the Automatically start this workflow when a new item is created option.

6. Check the Automatically start this workflow whenever an item is changed option.

7. Click Next.

8. Click Actions

Page 25: Custom Workflow Activities

9. Select the More Actions

10. In the Workflow Actions dialog box, click the dropdown for the Select a Category

and choose Extras.

Page 26: Custom Workflow Activities

11. In the Choose an Action box, select the Item Level Security activity in sharepoint

designer will appear and click Add.

12. Note that Apply security to this Document Library is displayed.

Page 27: Custom Workflow Activities

13. Click on this option in the Actions

14. From the Choose List Item dialog box, Select the Current Item option and click OK

15. Now the Actions is changed by displaying the current item's name.

16. Click Finish.

17. The Workflow can now be checked by creating a new InfoPath form, by

entering

the Authors and Readers fields.

18. Save the InfoPath form to the SharePoint site.

19. Select Manage Permissions from the Context Menu of the item saved and

check for

the permissions.

Page 28: Custom Workflow Activities

7. ConclusionThough this topic covers implementing Item Level Security by creating custom activity, the task can also be achieved by creating Item_Saved and Item_Updated Event Handlers for Lists. Though there are multiple ways of implementing the task, creating custom activity is more effective by means of reusability and lesser coding in VS 2005.

Add custom workflow activities to SharePoint Designer (Part 1)

Without a doubts one of the best things of MOSS 2007  is the new SharePoint Designer, and within him, the workflow designer, that  allows us speedy  and simple form to design workflows. 

As I have commented in other occasions, if we wish to make more complex workflows, or state machines, we need to use Visual Studio.  

SharePoint Designer, allows us to make sequential workflows with predetermined activities. Nevertheless, the possibility to extend the basic activities exists  and we can extend the functionality of ours workflows without  to write them completely in Visual Studio. Out-the-box, SharePoint Designer includes 22 actions. 

Page 29: Custom Workflow Activities

 Those actions are defined in the file WSS.ACTIONS, that resides in the directory “C:\Program Files\Common files\Microsoft Shared \web server extensions\12\1033\TEMPLAT\Workflow”.   In this file, the conditions and the actions that appear within SharePoint Designer are defined.

<Condition Name="Creado en un intervalo de fechas determinado" FunctionName="CreatedInRange" ClassName="Microsoft.SharePoint.WorkflowActions.Helper" Assembly="Microsoft.SharePoint.WorkflowActions,                   Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" AppliesTo="list" UsesCurrentItem="true"> <RuleDesigner Sentence="creado entre %1 y %2"> <FieldBind Id="1" Field="_1_" Text="fecha" DesignerType="Date"/> <FieldBind Id="2" Field="_2_" Text="fecha" DesignerType="Date"/> </RuleDesigner> <Parameters> <Parameter Name="_1_" Type="System.DateTime, mscorlib" Direction="In"/> <Parameter Name="_2_" Type="System.DateTime, mscorlib" Direction="In"/> </Parameters></Condition>

Herein,  we can see the assembled dll that handles the condition, to which elements  he is applied, and if it is possible to use the present item in the workflow.

Page 30: Custom Workflow Activities

Within the condition we have the rule for the designer, with the text that is going to appear; each rule uses a series of fields tags FieldBind, that connects with the necessary parameters in the assembled file.

Each tag FieldBind has an identifier that  corresponds with the position of the field within sentence ID=1, and that will be %1 in the sentence attribute as well.Also we can see attributes like Text, that will be the text by defect, and the DesignerType, that is the type of field.

After that, we have the section of Parameters with the different parameters that will go to the assembled file. The Name attribute has to correspond with the Field attribute of tag FieldBind, and the direction of the parameter needs to be In for input and Out for output. 

<Action Name="Establecer estado de aprobación del contenido" ClassName="Microsoft.SharePoint.WorkflowActions.SetModerationStatusActivity" Assembly="Microsoft.SharePoint.WorkflowActions, Version=12.0.0.0,                Culture=neutral, PublicKeyToken=71e9bce111e9429c" AppliesTo="list" ListModeration="true" Category="Acciones principales" UsesCurrentItem="true"> <RuleDesigner Sentence="Establecer estado de aprobación del contenido en %1 con %2"> <FieldBind Field="ModerationStatus" DesignerType="Dropdown" Id="1" Text="este estado"> <Option Name="Aprobado" Value="Approved"/> <Option Name="Rechazado" Value="Denied"/> <Option Name="Pendiente" Value="Pending"/> </FieldBind> <FieldBind Field="Comments" Text="comentarios" Id="2" DesignerType="TextArea" /> </RuleDesigner> <Parameters> <Parameter Name="ModerationStatus" Type="System.String, mscorlib" Direction="In" /> <Parameter Name="Comments" Type="System.String, mscorlib" Direction="Optional" /> <Parameter Name="__Context"       Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" /> <Parameter Name="__ListId" Type="System.String, mscorlib" Direction="In" /> <Parameter Name="__ListItem" Type="System.Int32, mscorlib" Direction="In" /> </Parameters></Action>

Now, we are going to see how the actions look in the same file; they are very similar to the conditions.  

Page 31: Custom Workflow Activities

The first part includes the assembled one that will take care to handle the action.The second one, are the rules for the designer. In this case the fields that has been used are a combobox (DesignerType= " Dropdown ") and a line of text (DesignerType= " TextArea ")The third part of the parameters, besides to use both fields defined in the rule of the designer, uses three additional parameters that are:

__Context: that it is the context of the WorkFlow.  __ListId: you go of the list with which we are working __ListItem:  the present item

With these three fields (that they are pre-established, so that we can use them whenever we want) we have as much control on the list as on the job stream that is being carried out.

At the moment A file XSD for this type of archives does not exist

Add custom workflow activities to SharePoint Designer (Part 2)

In order to add a new activity to our SharePoint Designer, first  we need to begin a WorkFlow project  in Visual Studio 2005,  concretely, a Workflow Activity Library (Workflow activity library).

From  this point we would create our activity; for this example I am going to create an activity that will send a text to the event viewer.

Page 32: Custom Workflow Activities

1: public partial class LogEventViewer : Activity 2: {

3:

4: public static DependencyProperty TextLogProperty =

5: DependencyProperty.Register("TextLog", typeof(string), typeof(LogEventViewer));

6:  

7: public LogEventViewer()

8: {

9: InitializeComponent();

10: }

11:  

12: /// <summary>

13: /// Valor que figurará en el visor de eventos

14: /// </summary>

15: /// <value>Texto</value>

16: [Description("Texto que saldrá en el visor de eventos")]

17: [Category("User")]

18: [Browsable(true)]

19: [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

20: public string TextLog

21: {

22: get { return (string) GetValue(TextLogProperty); }

23: set { SetValue(TextLogProperty, value); }

24: }

25:  

26: /// <summary>

27: /// Ejecución de la actividad

28: /// </summary>

29: /// <param name="provider">Contexto de ejecución de la actividad</param>

30: /// <returns></returns>

31: protected override ActivityExecutionStatus Execute(ActivityExecutionContext provider)

32: {

33: EventLog eventLog = new EventLog("Workflow");

Page 33: Custom Workflow Activities

34:  

35: eventLog.Source = "SharePoint Workflow";

36:  

37: try

38: {

39: eventLog.WriteEntry(TextLog, EventLogEntryType.Information);

40: }

41: finally

42: {

43: eventLog.Dispose();

44: }

45:  

46: return ActivityExecutionStatus.Closed;

47: }

48: }

 

First,  we  declare a dependent property of the workflow called TextLogProperty,  which we will use to pass the text that we wish to  show in the event viewer.

The internal property of the activity will be TextLog; this internal property obtains and establishes the value from the dependent property of the workflow.

Then we  define the Execute method, that  will be the  method in charge to  visualize the message in the event viewer.

A good practice is that the activities include a Validador, that I have omitted in the example but that is highly  recommended although  not obligatory, or if we want to use the activity inside of the visual studio workflow designer.

Once we have made the compilation, we can test it first (another good practice) creating an application to host the workflow and checking the activity.

Finally, after we are sure that our activity works correctly, we must install it in the GAC in our SharePoint server. And we need to modify the Web.config to include our assembly in the following section:

<System.Workflow.ComponentModel.WorkflowCompiler> <authorizedTypes> ......

Page 34: Custom Workflow Activities

<authorizedType Assembly="IdeSeg.SharePoint.Workflow.Activities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3bba710be857fdc1" Namespace="IdeSeg.SharePoint.Workflow.Activities" TypeName="*" Authorized="True" /> </authorizedTypes> </System.Workflow.ComponentModel.WorkflowCompiler>

 Now we  need to modify the file WSS.ACTIONS that we saw  in the first article in order to add our new action

<Action Name="Log en visor de eventos" ClassName="IdeSeg.SharePoint.Workflow.Activities.LogEventViewer" Assembly="IdeSeg.SharePoint.Workflow.Activities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3bba710be857fdc1" AppliesTo="all" Category="Personalizadas"> <RuleDesigner Sentence="Logear el evento siguiente %1"> <FieldBind Field="TextLog" Text="este mensaje" Id="1" DesignerType="TextArea"/> </RuleDesigner> <Parameters> <Parameter Name="TextLog" Type="System.String, mscorlib" Direction="In" /> </Parameters></Action>What we have done in the first place  is  authorize our assembly  so that  he is now an integral part of the  WorkFlow engine of SharePoint, and secondly, adding it  to the WSS.ACTIONS file, we have indicated to  the SharePoint Designer that  we have added a new activity.

When we use SharePoint Designer to publish a site, at the moment that we created a new workflow or we published  an existing one,  he communicates with SharePoint and recovers the File WSS.ACTIONS  to configurate the assistant of  the WorkFlow.

In this way the new actions will  be part of the file XOML that  the SharePoint Designer will create.  Finally the result within the SharePoint Designer will be as follow:

Page 35: Custom Workflow Activities

Creating your own Custom Workflow Activities as Components using Windows Workflow Foundation (Framework 3.0) and deployment on SharePoint 2007.

Required Installation Setup

Visual Studio .Net 2005 Framework 3.0 Windows Workflow Foundation Extension for Workflow Activity Template SharePoint Portal 2007,SharePoint Services and Microsoft Office SharePoint Designer

The steps to add a simple activity to the SharePoint Designer interface include:

1. Create a custom activity assembly.2. Sign and deploy the activity assembly to the GAC.3. Configure SharePoint to recognize the custom activity.4. Create a .ACTIONS file to be used by SharePoint Designer.

Step 1: Create a custom activity assembly

Open Visual Studio 2005 solution. Select New Project and Workflow Activity Library Template which is a project for

creating a library of activities which can later be reused as building blocks in workflows.

Code Block

using System;<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> using System.ComponentModel; using System.ComponentModel.Design;

Page 36: Custom Workflow Activities

using System.Collections; using System.Drawing; using System.Workflow.ComponentModel.Compiler; using System.Workflow.ComponentModel.Serialization; using System.Workflow.ComponentModel; using System.Workflow.ComponentModel.Design; using System.Workflow.Runtime; using System.Workflow.Activities; using System.Workflow.Activities.Rules; using System.Collections.Generic; using System.Text; namespace ActivityLibrary1 { public partial class ADComponent : System.Workflow.ComponentModel.Activity { private string cn; public ADComponent() { InitializeComponent(); } public static DependencyProperty DirectoryUriProperty = DependencyProperty.        Register"DirectoryUri",typeofSystem.String),typeo(ActivityLibrary1.ADComponent));        [DescriptionAttribute("Please specify the URI of the directory. Either an AD Server         or an XML File.")] [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)] [ValidationOption(ValidationOption.Required)] [BrowsableAttribute(true)] [Category("Directory")] public string DirectoryUri { get { return ((String)(base.GetValue(ADComponent.DirectoryUriProperty))); } set { base.SetValue(ADComponent.DirectoryUriProperty, value); } } public static DependencyProperty QueryProperty = DependencyProperty.Register        ("Query", typeof(System.String), typeof(ActivityLibrary1.ADComponent)); [DescriptionAttribute("Please specify the Username of the user to retrieve.")] [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)] [ValidationOption(ValidationOption.Optional)] [BrowsableAttribute(true)] [Category("Query")] public string Query { get { return ((String)(base.GetValue(ADComponent.QueryProperty))); } set { base.SetValue(ADComponent.QueryProperty, value);

Page 37: Custom Workflow Activities

} } public static DependencyProperty RetrievedUserDataProperty = Dependency         Property.Register ("RetrievedUserData", typeof(System.String), typeof        (ActivityLibrary1.ADComponent)); [DescriptionAttribute("Please specify the Username of the user to retrieve.")] [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)] [ValidationOption(ValidationOption.Optional)] [BrowsableAttribute(true)] [Category("RetrievedUserData")] public string RetrievedUserData { get { return ((String)(base.GetValue(ADComponent.RetrievedUserDataProperty))); } set { base.SetValue(ADComponent.RetrievedUserDataProperty, value); } } public string CN { get { return cn; } set { cn = value; } } protected override ActivityExecutionStatus Execute(ActivityExecutionContext         context) { string a = "ActiveDirectory"; switch (a) { case "ActiveDirectory": ADHelper adh = new ADHelper(this.DirectoryUri); CN = adh.FetchUser(this.Query); break; } //Set the results property this.RetrievedUserData = CN; return ActivityExecutionStatus.Closed; } }}

Code Bock For Supportive ADHelper Class

//-----------------------------------------------------------------------------// //--------------Active Directory helper Class----(Rifaqat:2nd April 06)-------// //-------Description: ...............................................--------//

Page 38: Custom Workflow Activities

//-------------------------------------------------------------------------//using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.DirectoryServices; using System.Collections; namespace ActivityLibrary1 { internal class ADHelper { private string ldapPath; DirectorySearcher search; internal ADHelper(string ldapPath) { this.ldapPath = ldapPath; search = new DirectorySearcher(new DirectoryEntry(ldapPath)); } internal string GetUsersManager(string loginName) { SearchResult result; search.Filter = String.Format("(SAMAccountName={0})", loginName); search.PropertiesToLoad.Add("manager"); result = search.FindOne(); if (result == null) { return ""; } else { string userPath = result.Properties["manager"][0].ToString(); System.DirectoryServices.DirectoryEntry de = new DirectoryEntry("LDAP://" +                userPath); return de.Properties["sAMAccountName"].Value.ToString(); } }   internal string FetchUser(string Designation) { string _User = ""; try { SearchResult result; search.Filter = String.Format("(Title={0})", Designation); search.PropertiesToLoad.Add("cn"); result = search.FindOne(); if (result != null) { _User = result.Properties["cn"][0].ToString(); } } catch (Exception ex) {

Page 39: Custom Workflow Activities

} return _User; } internal string FetchUseronDesg(string loginName) { string _User = ""; try { SearchResult result; search.Filter = String.Format("(SAMAccountName={0})", loginName); search.PropertiesToLoad.Add("title"); search.PropertiesToLoad.Add("cn"); result = search.FindOne(); if (result != null) { _User = result.Properties["title"][0].ToString(); } } catch (Exception ex) { string s = ex.Message; } return _User; } } }

Your Solution Explorer will be like this:

In this code the DirectoryUri and Query are passing as inputproperty and are used to specify the text that will be displayed in the Display Name of User as Output. We use a dependency property to enable the workflow to bind data to it. As with all workflow activities, the Execute method performs the action. 

Step 2: Sign and deploy the activity assembly to the GAC

Step 3: Configure SharePoint to recognize the custom activity

After you build the custom activity assembly, sign it and copy it to the GAC. You then have

Page 40: Custom Workflow Activities

to tell SharePoint to trust the assembly. This is similar to configuring a web part as a safe control, but instead of adding an entry to the <SafeControls> section, you add an entry to the <System.Workflow.ComponentModel.WorkflowCompiler> section. Edit the web.config file for your SharePoint web application and add an <authorizedType> element as in the following example:

Goto in your Site using this URL C:\Inetpub\wwwroot\wss\VirtualDirectories\10161 Open your Config File. You need to add your assembly in specific site port config file:

<authorizedType Assembly="rifaqat.Components, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e8f8c868b9896b0a" Namespace="rifaqat.Components" TypeName="*" Authorized="True" /><authorizedType Assembly="ActivityLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8fd4b4c3a190a3c6" Namespace="ActivityLibrary1" TypeName="*" Authorized="True" />

Step 4: Create a .ACTIONS file to be used by SharePoint Designer The final step is to create the .ACTIONS file that describes the activity to SharePoint

Designer. Since this is an XML file, you can create it using Visual Studio or any XML editor.

This file describes the public properties exposed by the activity and tells SharePoint Designer how to map those properties into rules that can be displayed to the user. The following code shows a custom .ACTIONS file for the custom Active Directory activity.

Goto this path for .Actions File

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\Workflow

<?xml version="1.0" encoding="utf-8" ?> <WorkflowInfo> <Actions Sequential="then" Parallel="and"> <Action Name="Fetch User Onbehalf of Designation" ClassName="Microsoft.SharePoint.WorkflowActions.CollectDataTask" Assembly="Microsoft.SharePoint.WorkflowActions, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" AppliesTo="all" CreatesTask="true" Category="Task Actions"> <RuleDesigner Sentence="Collect %1 from %2 (Output to %3)"> <FieldBind Field="Title,ContentTypeId" DesignerType="Survey" Text="data" Id="1"/> <FieldBind Field="AssignedTo" DesignerType="SinglePerson" Text="this user"Id="2"/> <FieldBind Field="TaskId" DesignerType="ParameterNames" Text="collect" Id="3"/> </RuleDesigner> <Parameters> <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.         WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In" /> <Parameter Name="ContentTypeId" Type="System.String, mscorlib"Direction="In" /> <Parameter Name="AssignedTo" Type="System.String, mscorlib" Direction="In" /> <Parameter Name="Title" Type="System.String, mscorlib" Direction="In" /> <Parameter Name="TaskId" Type="System.Int32, mscorlib" Direction="Out" /> </Parameters> </Action> </Actions> </WorkflowInfo>

Page 41: Custom Workflow Activities

The Actions tag tells SharePoint Designer what to display for each action in the set. Within that, the Action tag describes the individual action. The Name attribute is what gets displayed in the designer. The ClassName and Assembly attributes are used in the generated XAML for the workflow. The interesting part is the way the RuleDesigner and Parameter tags work. The RuleDesigner tag lets you set up a sentence that gets displayed in the designer as you build up the workflow. The Sentence attribute allows you to bind to the activity properties and then substitute their values when the activity is executed.

You can declare as many actions as you want in the file. A good rule of thumb is to use a separate .ACTIONS file for each logical group of custom activities you wish to deploy. Once you've created your .ACTIONS file and copied it to the server, you can refresh the site in SharePoint Designer and your custom activity will appear in the workflow designer as shown below.

Site Definition in SharePoint By  Dhananjay Kumar January 08, 2009

This article will explain about Site Definition, why we do need custom site definition ?and how to create and deploy a custom site definition.

Page 42: Custom Workflow Activities

Site Definition

Site Definitions are the foundations on which all sites and user templates are built.  Site Definition is collection ox XML and .aspx file. Site Definitions are predefined components needs to be included when a site was

created in SharePoint server. Site Definition contains information of Web Part , Lists, Features and navigation bars

to be included in the site. Customizing Portal Sites and other SharePoint sites using Site Definition is most

appropriate for third party developer and SharePoint Administrator. Site Definitions requires access to a file system of the Web Server. Server administrator must be also involved in deployment of Site Definitions.  Custom Site Definitions are Version and Upgrade independent.  Subsequent upgrades to SharePoint products  and technologies may overwrite 

existing Site Definitions. Using Custom Site definition exclude site from potential upgrade issues. 

To avoid Unghosting  , Custom Site Definition is to be create. There are two options to create it

1. Create New Site Definition File : Either Start from Scratch and create files one by one  or Copy an existing Site Definition and modify it.

2. Copy a Site Definition and change it in Visual Studio:   We can make copy an existing site definition and modify it in visual studio to create new site definition.

The configuration of this site definitions are defined in XML file which is available in

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\XML folder.

In the file system these definitions are available in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\Site Templates.

Each of these site definitions consists a XML folder and a Home page (default.aspx).

Steps to create custom Site Definition

1. Log on as an administrator

2. Browse to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\SiteTemplates.

Copy STS folder-> Paste it at same place -> Rename it as TIGER.

3. Open the folder Tiger

4. Search for default.aspx

5. Open default.aspx in notepad.

6. Modify code. Here we need to add code for site definition.

Default.aspx

<%@ Page language="C#" MasterPageFile="~masterurl/default.master"

Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=12.0.0.0,Culture=neutral,P

ublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="SharePoint"

Page 43: Custom Workflow Activities

Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral,

PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="Utilities"

Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral,

PublicKeyToken=71e9bce111e9429c" %> <%@ Import Namespace="Microsoft.SharePoint" %> <%@ Register

Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint,

Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<asp:Content ID="Content1" ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">

<SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,multipages_homelink_text%>"

EncodeMethod="HtmlEncode"/> - <SharePoint:ProjectProperty Property="Title" runat="server"/>

</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderId="PlaceHolderPageImage" runat="server"><IMG

SRC="/_layouts/images/blank.gif" width=1 height=1 alt=""></asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">

<label class="ms-hidden"><SharePoint:ProjectProperty Property="Title"

runat="server"/></label>

</asp:Content>

<asp:Content ID="Content4" ContentPlaceHolderId="PlaceHolderTitleBreadcrumb" runat="server"/>

<asp:Content ID="Content5" ContentPlaceHolderId="PlaceHolderTitleAreaClass" runat="server">

<style type="text/css">

TD.ms-titleareaframe, .ms-pagetitleareaframe {

height: 10px;

Page 44: Custom Workflow Activities

}

Div.ms-titleareaframe {

height: 100%;

}

.ms-pagetitleareaframe table {

background: none;

height: 10px;

}

</style>

</asp:Content>

<asp:Content ID="Content6" ContentPlaceHolderId="PlaceHolderAdditionalPageHead" runat="server">

<META Name="CollaborationServer" Content="SharePoint Team Web Site">

<script type="text/javascript">

var navBarHelpOverrideKey = "wssmain";

</script>

</asp:Content>

<asp:Content ID="Content7" ContentPlaceHolderId="PlaceHolderSearchArea" runat="server">

<SharePoint:DelegateControl runat="server"

ControlId="SmallSearchInputBox" />

</asp:Content>

<asp:Content ID="Content8" ContentPlaceHolderId="PlaceHolderLeftActions" runat="server">

</asp:Content>

<asp:Content ID="Content9" ContentPlaceHolderId="PlaceHolderPageDescription" runat="server"/>

<asp:Content ID="Content10" ContentPlaceHolderId="PlaceHolderBodyAreaClass" runat="server">

Page 45: Custom Workflow Activities

<style type="text/css">

.ms-bodyareaframe {

padding: 0px;

}

</style>

</asp:Content>

<asp:Content ID="Content11" ContentPlaceHolderId="PlaceHolderMain" runat="server">

<table cellspacing="0" border="0" width="100%">

<tr>

<td class="ms-pagebreadcrumb">

<asp:SiteMapPath SiteMapProvider="SPContentMapProvider" id="ContentMap" SkipLinkText=""

NodeStyle-CssClass="ms-sitemapdirectional" runat="server"/>

</td>

</tr>

<tr>

<td class="ms-webpartpagedescription"><SharePoint:ProjectProperty Property="Description"

runat="server"/></td>

</tr>

<tr>

<td>

<table width="100%" cellpadding=0 cellspacing=0 style="padding: 5px 10px 10px 10px;">

<tr>

<td valign="top" width="100%" colspan="3">

<WebPartPages:WebPartZone runat="server" FrameType="TitleBarOnly" ID="Top" Title="loc:Top" />

</td>

Page 46: Custom Workflow Activities

</tr>

<tr>

<td valign="top" width="70%">

<WebPartPages:WebPartZone runat="server" FrameType="TitleBarOnly" ID="Left"

Title="loc:Left" />

&nbsp;

</td>

<td>&nbsp;</td>

<td valign="top" width="30%">

<WebPartPages:WebPartZone runat="server" FrameType="TitleBarOnly" ID="Right"

Title="loc:Right" />

&nbsp;

</td>

<td>&nbsp;</td>

</tr>

</table>

</td>

</tr>

<tr>

<td valign=â€topâ€� � width=â€100%â€� � colspan=â€3â€� �>

<WebPartPages:WebPartZone runat="server" FrameType="TitleBarOnly" ID="Bottom"

Title="loc:Bottom" />

</td>

</tr>

</table>

</asp:Content>

Page 47: Custom Workflow Activities

7. Register new site definition to SharePoint.

8. Open the folder

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\XML

9. Copy the file WEBTEMP.XML and save it as WEBTEMPTIGER.xml. here make a note that , we need to append name of folder which we created in step 2 ( in this case it is tiger) to WEBTEMP. So here name would be WEBTEMPTIGER.xml

10. Open WEBTEMPTIGER.XML in notepad and replace it with following content.

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

<!-- _lcid="1033" _version="12.0.4518" _dal="1" -->

<!-- _LocalBinding -->

<Templates xmlns:ows="Microsoft SharePoint">

<Template Name="TIGER" ID="10009">

<Configuration ID="1" Title="Tiger Definition" Hidden="FALSE" ImageUrl="/_layouts/images/Eye.GIF" Description="Tiger Site." DisplayCategory="Custom" AllowGlobalFeatureAssociations="False" > </Configuration>

</Template>

</Templates>

Make sure here ID should be greater than 10000. It must not collide with id of any other Site Definition.

11. Restart IIS. Go to Start->Run->IISRESET

12. Now you would be able to see this Site Definition inside Custom category.

Page 48: Custom Workflow Activities