Steps to create SharePoint Workflow with “Custom Task Form” in SharePoint 2010 using Visual Studio
Steps to create
SharePoint Workflow with “Custom Task Form” in SharePoint 2010 using Visual
Studio
What we are
going to do?
When create new a requirement => will
appear a register form (ASPX Form), after register successful, workflow auto
run and send Task for any people, and that requirement when people receive it
will open Task to Approve on form (ASPX Form)
Steps:
·
Create new content type
for list Target
·
Create new List Definition
for list Target
·
Create new module
·
Create new custom .aspx
form (application page) for List Target
·
Create new content type
for list task
·
The custom .aspx form
(application page) for List Task
·
Create new basic workflow
·
Create new Event Receiver
to active workflow run when add content type item
How to
Start?
Open visual studio -> New Project -> Visual
C# -> Sharepoint 2010 -> Empty Sharepoint Project -> name ít “Online_Tutor”
Choose “Deploy as a farm solution”
Create
new content type for list Target
Right click to project -> New Item ->
Content type -> name is
Online_Tutor_ContentTypeTargetList -> Choose Content
Type Item
Create
new List Definition for list Target
Right click to project -> Add new item ->
List Definition From Content Type -> Name is Online_Tutor_ListDefinition_TargetList
Choose content type inherit from content
type “Online_Tutor_ContentTypeTargetList” had created above
Structure of List Definition as follows :
·
change
100 number in Element.xml file of ListInstance1 if you want to your List is
custom list
·
Must
change 100 number in Element file of Online_Tutor_ListDefinition_TargetList
This is structure of Schema.xml in Online_Tutor_ListDefinition_TargetList
list
In tag <FieldRefs> </
FieldRefs> insert Fields as follows
<!--Insert to here-->
<FieldRef ID="FA564E0F-0C70-4AB9-B863-0177E6DDD247" Name="Title" Hidden="TRUE" Required="FALSE"/>
<FieldRef ID="{D37DE7CA-1296-47CF-91EB-2C8D09D94C00}" Name="Description" />
<!--End
Insert to here-->
Insert the segment code to register form
aspx when display you Add New Item
<!--Insert to here-->
<XmlDocuments>
<XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<Display>ListForm</Display>
<Edit>ListForm</Edit>
<New>ListForm</New>
</FormTemplates>
</XmlDocument>
<XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
<FormUrls xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url" >
<New>Form/TargetList_AddNew.aspx</New>
</FormUrls>
</XmlDocument>
</XmlDocuments>
<!--End Insert to here-->
In tag <Fields> </Fields>
insert segment code as follows
<!--Insert to here-->
<Field Type="Text" ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" ReadOnly="TRUE" Required="FALSE" Hidden="TRUE"
SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="Title"></Field>
<Field ID="{d37de7ca-1296-47cf-91eb-2c8d09d94c00}" Type="Text" Name="Description" DisplayName="Description" />
<!--End Insert to here-->
Create
Module
Right click to Project -> Add new Item ->
Module -> name is Form
then delete file Sample.txt
Create
new custom aspx form (application page) for List Target
Right click to Project -> Add new Item ->
Application Page -> name is TargetList_AddNew.aspx
Application Page structure as follows
Change DynamicMasterPageFile to
MasterPageFile by delete Dynamic character
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TargetList_AddNew.aspx.cs"
Inherits="Online_Tutor.Layouts.Online_Tutor.TargetList_AddNew" PageFile="~masterurl/default.master" %>
Copy segment code into PlaceHolderMain
<table style="width: 900px;">
<tr>
<td class="column1">
Test
</td>
<td class="column2">
<asp:TextBox ID="TextBox_HoTen" runat="server" Width="309px"></asp:TextBox>
</td>
</tr>
</table>
Copy Target list to PlaceHolderAdditionalPageHead,
PlaceHolderPageTitle, PlaceHolderPageTitleInTitleArea
Using
and change class inherit from LayoutsPageBase to WebPartPage as follows:
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Utilities;
Copy code
Button_Submit_Click, Button_Cancel_Click, CloseForm below Page_Load method
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Utilities;
namespace Online_Tutor.Layouts.Online_Tutor
{
public partial class TargetList_AddNew : WebPartPage
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button_Submit_Click(object sender, EventArgs e)
{
SPList spList = SPContext.Current.List;
SPListItem spListItem = spList.Items.Add();
spListItem["Title"] = txtDescription.Text + "";
spListItem["Description"] = txtDescription.Text + "";
spListItem.Update();
spList.Update();
CloseForm();
}
protected void Button_Cancel_Click(object sender, EventArgs e)
{
CloseForm();
}
private void CloseForm()
{
if ((SPContext.Current
!= null) && SPContext.Current.IsPopUI)
{
this.Context.Response.Write("<script
type='text/javascript'>window.frameElement.commitPopup();</script>");
this.Context.Response.Flush();
this.Context.Response.End();
}
else
{
string str = this.Page.Request.QueryString["Source"];
if ((str != null)
&& (str.Length > 0))
{
SPUtility.Redirect(string.Empty, SPRedirectFlags.UseSource, this.Context);
}
}
}
}
}
Cut TargetList_AddNew.aspx into Form Module
You see the path auto insert to file
Element.xml of Form module
Deploy Project create new Item content type
as follows
:
Create
new content type for list task
Right click to project -> Add new item ->
Content type -> Online_Tutor_ContentTypeTask
Choose Task Content Type
You
see default number string of content type Task is 0x010800 you must change to
0x01080100
After change number then delete Inherits=
“True” properties (image 30)
After number string was changed and
Inherits= “True” properties was deleted, result as follows
Below close tag </FieldRefs> insert
code to know path of Form Display and Edit of Task form
Create
new custom aspx form (application page) for List Task
Right click to project -> New Item ->
Application Page -> Name is CustomFormTaskList.aspx
Change DynamicMasterPageFile to
MasterPageFile by delete Dynamic character
Copy code into PlaceHolderMain
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
<!--Insert code to here-->
<table style="width: 500px;" class="lcttable">
<tr>
<td>
Description
</td>
<td>
<%=Description%>
</td>
</tr>
<tr>
<td>
</td>
<td>
<asp:Button ID="Button_Ok" runat="server" Text="OK" Width="100px" OnClick="Button_Ok_Click" />
<asp:Button ID="Button_Cancel" runat="server" Text="Cancel" Width="100px" OnClick="Button_Cancel_Click" />
</td>
</tr>
</table>
<!--End Insert code to here-->
</asp:Content>
Copy Custom Form Task List to
PlaceHolderAdditionalPageHead, PlaceHolderPageTitle,
PlaceHolderPageTitleInTitleArea
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CustomFormTaskList.aspx.cs"
Inherits="Online_Tutor.Layouts.Online_Tutor.CustomFormTaskList"
MasterPageFile="~masterurl/default.master" %>
<asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
Custom Form Task List
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
<!--Insert code to here-->
<table style="width: 500px;" class="lcttable">
<tr>
<td>
Description
</td>
<td>
<%=Description%>
</td>
</tr>
<tr>
<td>
</td>
<td>
<asp:Button ID="Button_Ok" runat="server" Text="OK" Width="100px" OnClick="Button_Ok_Click" />
<asp:Button ID="Button_Cancel" runat="server" Text="Cancel" Width="100px" OnClick="Button_Cancel_Click" />
</td>
</tr>
</table>
<!--End Insert code to here-->
</asp:Content>
<asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
Custom Form Task List
</asp:Content>
<asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">
Custom Form Task List
</asp:Content>
Using and change class inherit from
LayoutsPageBase -> WebPartPage
Copy code as follows
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;
namespace Online_Tutor.Layouts.Online_Tutor
{
public partial class CustomFormTaskList : WebPartPage
{
public string Description;
protected void Page_Load(object sender, EventArgs e)
{
try
{
SPListItem spListItem = SPContext.Current.ListItem;
string urlLink = spListItem["WorkflowLink"].ToString().Split(',')[0];
int idItem = Convert.ToInt32(urlLink.Split('=')[1]);
SPSite ObjSite;
SPWeb ObjWeb;
SPSecurity.RunWithElevatedPrivileges(delegate
{
using (ObjSite = new SPSite(SPContext.Current.Site.ID))
{
using (ObjWeb = ObjSite.RootWeb)
{
SPList objList = ObjWeb.GetListFromUrl(urlLink);
SPListItem target = objList.GetItemById(idItem);
Description = target["Description"] + "";
string action = Page.Request.QueryString["action"] + "";
if (action
== "display")
{
Button_Cancel.Visible = false;
Button_Ok.Visible = false;
}
}
}
});
}
catch
{
// Nothing
}
}
protected void Button_Ok_Click(object sender, EventArgs e)
{
try
{
SPListItem spListItem = SPContext.Current.ListItem;
if (spListItem.ParentList.ContentTypes[SPBuiltInContentTypeId.SummaryTask] != null)
{
spListItem.ParentList.ContentTypes.Delete(SPBuiltInContentTypeId.SummaryTask);
}
if (spListItem.ParentList.ContentTypes[SPBuiltInContentTypeId.Task] != null)
{
spListItem.ParentList.ContentTypes.Delete(SPBuiltInContentTypeId.Task);
}
spListItem["PercentComplete"] = 1F;
spListItem.Update();
CloseForm();
}
catch
{
// Nothing
}
}
protected void Button_Cancel_Click(object sender, EventArgs e)
{
SPListItem spListItem = SPContext.Current.ListItem;
spListItem["PercentComplete"] = 0;
spListItem.Update();
CloseForm();
}
private void CloseForm()
{
if ((SPContext.Current
!= null) && SPContext.Current.IsPopUI)
{
this.Context.Response.Write("<script
type='text/javascript'>window.frameElement.commitPopup();</script>");
this.Context.Response.Flush();
this.Context.Response.End();
}
else
{
string str = this.Page.Request.QueryString["Source"];
if ((str != null)
&& (str.Length > 0))
{
SPUtility.Redirect(string.Empty, SPRedirectFlags.UseSource, this.Context);
}
}
}
}
}
Cut CustomFormTaskList.aspx from Layouts
Folder to Form module
Create
new basic workflow
Right to Project -> Add New Item ->
Sequential Workflow -> Name is Online_Tutor_Workflow
Choose List Workflow
Design workflow as follow
Configure properties for
createTaskWithContentType1 (reference how to create workflow sequential
at here part How to create
workflow approval)
Configure properties for onTaskChanged1
Configure properties for
logToHistoryListActivity1
Double click to createTaskWithContentType1
Paste code to
createTaskWithContentType1_MethodInvoking (note: ID content type of list task
is same)
private void createTaskWithContentType1_MethodInvoking(object sender, EventArgs e)
{
createTaskWithContentType1_TaskId1 = Guid.NewGuid();
createTaskWithContentType1_ContentTypeId1 = "0x0108010059177a2760644cd3b054dd3f929e0380";
createTaskWithContentType1_TaskProperties1.AssignedTo
= "win-67038mbkel7\\administrator";
createTaskWithContentType1_TaskProperties1.Title = "Custom From ASPX Task List ";
}
Double click to onTaskChanged1
paste code to onTaskChanged1_Invoked
private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)
{
onTaskChanged1_AfterProperties1.PercentComplete = 1F;
}
//All Code
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
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 Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
namespace BasicWFASPXTaskForm.BasicWFASPXTaskForm_Workflow
{
public sealed partial class BasicWFASPXTaskForm_Workflow : SequentialWorkflowActivity
{
public BasicWFASPXTaskForm_Workflow()
{
InitializeComponent();
}
public Guid workflowId = default(System.Guid);
public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
public Guid createTaskWithContentType1_TaskId1
= default(System.Guid);
public SPWorkflowTaskProperties createTaskWithContentType1_TaskProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
public String createTaskWithContentType1_ContentTypeId1
= default(System.String);
public SPWorkflowTaskProperties onTaskChanged1_AfterProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
public SPWorkflowTaskProperties onTaskChanged1_BeforeProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
private void createTaskWithContentType1_MethodInvoking(object sender, EventArgs e)
{
createTaskWithContentType1_TaskId1 = Guid.NewGuid();
createTaskWithContentType1_ContentTypeId1 = "0x01080100349325c1e86c4e8c992a9a1c041fbcd1";
createTaskWithContentType1_TaskProperties1.AssignedTo = "win-67038mbkel7\\administrator";
createTaskWithContentType1_TaskProperties1.Title = "Custom ASPX From Task List";
}
private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)
{
onTaskChanged1_AfterProperties1.PercentComplete = 1F;
}
}
}
////////////////////////////////////
***End All Code ***////////////////////////////////////
Open file Element.xml of Workflow and
change as follow
Create
new Event Receiver to call workflow run when add content type item
delete Feature2 when workflow was created (no
require)
Open Feature1 change scope from web to site
Move feature workflow to right
Right click to Feature1 -> Add Event
Receiver
Using : using Microsoft.SharePoint.Workflow; and declare 3 variable
private string _workflowName
= "Online_Tutor - Online_Tutor_Workflow";
private string _contentTypeName
= "Online_Tutor - Online_Tutor_ContentTypeTargetList";
private string nameWorkflowOnContentType
= "Wf
CustomASPXTaskForm";
////////////////////////////////////// ***
All code *** //////////////////////////////////////
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Workflow;
namespace Online_Tutor.Features.Feature1
{
/// <summary>
/// This class handles events raised during feature
activation, deactivation, installation, uninstallation, and upgrade.
/// </summary>
/// <remarks>
/// The GUID attached to this class may be used during
packaging and should not be modified.
/// </remarks>
[Guid("c52f6eae-fc7e-47a5-89e1-3b2b0fa32c2b")]
public class Feature1EventReceiver : SPFeatureReceiver
{
private string _workflowName
= "Online_Tutor - Online_Tutor_Workflow";
private string _contentTypeName
= "Online_Tutor - Online_Tutor_ContentTypeTargetList";
private string nameWorkflowOnContentType
= "Wf
CustomASPXTaskForm";
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using (SPSite site = ((SPSite)properties.Feature.Parent))
{
using (SPWeb web =
site.OpenWeb())
{
SPContentType theCt =
web.ContentTypes[_contentTypeName];
SPWorkflowTemplate theWf = null;
foreach (SPWorkflowTemplate tpl in web.WorkflowTemplates)
{
if (tpl.Name == _workflowName)
{
theWf = tpl;
}
}
SPWorkflowAssociation wfAssociation =
theCt.WorkflowAssociations.GetAssociationByName(nameWorkflowOnContentType,
web.Locale);
if (wfAssociation != null)
{
theCt.WorkflowAssociations.Remove(wfAssociation);
}
theCt.UpdateWorkflowAssociationsOnChildren(true, true, true, false);
// Name of workflow on ContentType that is
associated to definition workflow
wfAssociation = SPWorkflowAssociation.CreateWebContentTypeAssociation(theWf,
nameWorkflowOnContentType, "Task Online_Tutor", "History Online_Tutor");
wfAssociation.AutoStartCreate = true;
wfAssociation.AutoStartChange = true;
if (theCt.WorkflowAssociations.GetAssociationByName(wfAssociation.Name,
web.Locale) == null)
{
theCt.WorkflowAssociations.Add(wfAssociation);
}
else
{
theCt.WorkflowAssociations.Update(wfAssociation);
}
theCt.UpdateWorkflowAssociationsOnChildren(true, true, true, false);
}
}
}
// Uncomment the method below to handle the
event raised before a feature is deactivated.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
using (SPSite site = ((SPSite)properties.Feature.Parent))
{
using (SPWeb web =
site.OpenWeb())
{
SPContentType theCt =
web.ContentTypes[_contentTypeName];
SPWorkflowAssociation wfAssociation =
theCt.WorkflowAssociations.GetAssociationByName(_workflowName, web.Locale);
if (wfAssociation != null)
{
theCt.WorkflowAssociations.Remove(wfAssociation);
}
theCt.UpdateWorkflowAssociationsOnChildren(true, true, true, false);
}
}
}
// Uncomment the method below to handle the
event raised after a feature has been installed.
//public override void
FeatureInstalled(SPFeatureReceiverProperties properties)
//{
//}
// Uncomment the method below to handle the
event raised before a feature is uninstalled.
//public override void FeatureUninstalling(SPFeatureReceiverProperties
properties)
//{
//}
// Uncomment the method below to handle the
event raised when a feature is upgrading.
//public override void
FeatureUpgrading(SPFeatureReceiverProperties properties, string
upgradeActionName, System.Collections.Generic.IDictionary<string, string>
parameters)
//{
//}
}
}
////////////////////////////////////// ***
End All code *** //////////////////////////////////////
Deploy project, you see list definition was
created as follows
Create new item
Workflow run automatically
Edit Item
Appear ASPX form in list Task
After approve (OK) status of workflow is
completed
Note:
·
Error cannot Add solution
=> change name of content type
·
Error cannot Active solution
=> change Name WF, Name content type in event receiver same with in xml file
of workflow and content type target list
·
Error failing in started =>
insert ContentType;# to
<AssociationCategories>ContentType;#List</AssociationCategories>
·
Error cannot display Form
ASPX=> delete List contain that Form then deploy
Comments
Post a Comment