Quantcast
Viewing all articles
Browse latest Browse all 9

Creating SPD 2013 Workflows. Part 2/3: implementing custom ASP.Net task form

Hi!

This is the second post of the series related to SPD 2013 Workflows. In this post I will show you how to implement custom ASP.Net task form and embed it into your workflow. Some parts of this task are straightforward; However, there are several pitfalls and changes from SP2010.

This series consists of 3 parts:

1. Creating extremely simple workflow with the default task form. This part is for very beginners only and if you know how to create simple SPD workflow you can skip this part without any risks to not to understand the following parts, but if you are a beginner, it is the right place to start!

2. Implementing custom ASP.NET task form and embeding it to a workflow (this part). In this part you could find information how to create custom task forms. Also in this part you can find the answer on the question “How to complete a task or change an assignee if old SP2010 methods don’t work anymore?”.

3. Tips and hints of custom ASP.NET task forms creation. In this part you can find information how to implement reusable parts of task forms, how to force SP controls work as expected after changing context, how to create analogue of the Request Changes behavior which was built-in in SP2010, but should be implemented by yourself in SP2013 and some other techniques!

Let’s get started!


Steps overview:

  1. Step 1. Creating custom ASP.NET task form.
  2. Step 2. Making task activity to use the new custom task form.
  3. Step 3. Adding form logic for showing and completing a task.
  4. Conclusion.

Step 1. Creating custom ASP.NET task form.

1. Create new SharePoint 2013 empty project.

For that open Visual Studio 2012 and create a new project.

Image may be NSFW.
Clik here to view.
130227_03

Select the “SharePoint 2013 – Empty Project” template.

note: If you can’t see this template then, most likely, you didn’t install Microsoft Office Developer Tools for Visual Studio 2012. These tools are necessary for the most of the development tasks for SharePoint in Visual Studio.

Image may be NSFW.
Clik here to view.
130227_04
 

Enter the URL of your SP site and select “Deploy as a farm solution”.

Image may be NSFW.
Clik here to view.
130227_05

2. Add SharePoint “Layouts” Mapped Folder in your project.

For that you could right-click on your project, select “Add” and then “SharePoint ‘Layouts’ Mapped Folder”.

Image may be NSFW.
Clik here to view.
130227_06

3. Add new Application page in your project.

For that, you should right click on the folder with the name of your project in the Layouts. Select “Add” \ “New Item…”, then select “Application Page (Farm Solution only)” and fill in name for our first ASP.NET task form (“MyCustomTaskForm.aspx” in my example).

Image may be NSFW.
Clik here to view.
130227_07

Image may be NSFW.
Clik here to view.
130227_08

Visual Studio will create a default Application Page which will be similar to this one shown on the screenshot below. Have a look at the text inside the “asp:Content” with IDs “PageTitle” and “PageTitleInTitleArea”. Where are strings “Application Page” and “My Application Page”.Image may be NSFW.
Clik here to view.
130309_blog_01

Results of the first step: We have just created a simple ASP.NET page. Now, you can test, whether you could see it in your browser. For this, you could press CTRL-F5 in VS to deploy your project and enter path to your form (“YourSiteUrl/_layouts/15/Custom2013TaskForms/MyCustomTaskForm.aspx”) in your browser. You should see your first form (for a while it contains only from the Title “My Application Page”).

Image may be NSFW.
Clik here to view.
130309_blog_02


Step 2. Making task activity to use the new custom task form.

During this step we have to create a new content type which is derived from the “Workflow Task (SharePoint 2013)” one, add it to Workflow Tasks list, change edit form of our content type to the new one created by us in the first step. After that we should change task content type to ours in the workflow task action.

This part seems to be done very easily; however, there are some pitfalls where I spent a lot of time to understand how to do it correctly.

Pitfall: There is an issue in content types which use inheritance. It is impossible to change forms (New, Display and Edit) for content types which are derived from others. When you change link to their forms using SPD or the special tags in declarative XML definition it just doesn’t work. SP doesn’t show you any error messages, you just see standard forms instead of the custom ones. However, as you remember, we have to derive our task content type from “Workflow Task (SharePoint 2013)” to be able to customize it. So, we come to a paradoxical situation. On the one hand we should create new inherited task content type to be able to customize it, but on the other hand it is impossible to use custom forms for the content type if it is inherited.

Workaround: Fortunately, we can change forms of derived content type using SP Object model (this way works correctly for the derived content types).

1. Create a new Content Type derived from the “Workflow Task (SharePoint 2013)”.

For that open your site collection in SPD, select “Content Types” in the “Site Objects” and press the Content Type button in the ribbon. After that fill in name and description of the new custom task content type.

Important: Select parent content type “Workflow Task (SharePoint 2013)” which is located in the “List Content Types” group.

Image may be NSFW.
Clik here to view.
130309_blog_03

 

2. Add new content type to the list of content types for the “Workflow Tasks” list.

Important: This is a mandatory step to be able to use custom task content type. If you don’t add it, you will get strange error messages when WF tries to assign a task.

For that you can open this list in SPD.

Image may be NSFW.
Clik here to view.
130309_blog_04

Make sure that management of content type is enabled for this list (checkbox A is ticked). Press the “Add…” button, select new task content type and press OK.

Image may be NSFW.
Clik here to view.
130309_blog_05

After that you should see new content type in the list of Content Types for Workflow Task list.

Image may be NSFW.
Clik here to view.
130309_blog_06

 

3. Change edit form of our task content type to the form we have created in the first part.

One of the possible ways to do this is to use Feature Event Receiver. For that we should add a feature and an Event Receiver.

Image may be NSFW.
Clik here to view.
130309_blog_07
Image may be NSFW.
Clik here to view.
130309_blog_08

VS creates default Event Receiver for us. We have to uncomment FeatureActivated method and add our code which will change Edit form for our content type inside of it.

Piece of code for copy-paste:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        using (SPWeb web = (SPWeb)properties.Feature.Parent)
        {
            SPContentType ct = web.ContentTypes["MyTaskContentType"];
            ct.EditFormUrl = "_layouts/15/Custom2013TaskForms/MyCustomTaskForm.aspx";
            ct.Update(true);
        }
    }

Our FeatureActivated method of the Event Receiver should look as follows in VS:

Image may be NSFW.
Clik here to view.
130309_blog_10

4. Change Content type of our task activity in Workflow from the default “Workflow Task (SharePoint 2013)” to our new “MyTaskContentType” one.

For that we should open our “Request supplies” workflow (which was created in the previous part of this series) in SPD.

Image may be NSFW.
Clik here to view.
130309_blog_11
Image may be NSFW.
Clik here to view.
130309_blog_12

Open task process for editing (click on the assignee).

Image may be NSFW.
Clik here to view.
130309_blog_13

 

Change task content type field in the Outcome Options section to our custom task content type (MyTaskContentType).

Image may be NSFW.
Clik here to view.
130309_blog_14

Save changed workflow and publish it by pressing buttons in the ribbon.

Image may be NSFW.
Clik here to view.
130309_blog_15

 

5. Deploy our project using VS and make sure that Edit form for our content type is changed.

For that, press CTRL-F5 in VS (our project deploys and Event Receiver changes edit form for our content type).

To check whether edit form is changed, we could press F5 in SPD to get the latest information from the server, and select our content type.

Image may be NSFW.
Clik here to view.
130309_blog_16

We should see that now it uses our ASP.NET form, which was created on the first step.

Image may be NSFW.
Clik here to view.
130309_blog_17

6. Check whether default task form has changed to our new one.

To check it we should start new instance of the “Request supplies” workflow and edit the “Provide office supplies” task.

For that open list “Office supplies requests” in a browser, select an item (or create a new one) and start workflow on it by clicking “…” \ “Workflows” \ “Request supplies”.

Image may be NSFW.
Clik here to view.
130309_blog_18
Image may be NSFW.
Clik here to view.
130312_blog_01

 

Open list of tasks for WF which we have just started. You can do this in two different ways:

a) click “…” \ “Workflows” and select “Request supplies” from the list of running workflows. Make sure that this is a new version of workflow by looking on its date. If you can’t see the new WF, wait a bit and periodically refresh your browser (F5). Starting of the new WF usually takes not more than half a minute.

Image may be NSFW.
Clik here to view.
130312_blog_03

 

Image may be NSFW.
Clik here to view.
130312_blog_04

 

b)  Or alternatevely, just click on the status link for the Request supplies workflow. However, in this case you should wait a bit and refresh your browser (F5) to make sure, that this link is related to the WF you have just started and not to WF, which was started some time ago.

Image may be NSFW.
Clik here to view.
130312_blog_05

 

You should see a new task “Provide office supplies”. Press “V” \ “Edit” and our ASP.NET task form should appear (as you remember for the moment it consist from the Title “My Application Page” only).

Image may be NSFW.
Clik here to view.
130312_blog_06

Image may be NSFW.
Clik here to view.
130312_blog_07

 

Results of this step: We have created a custom task content type which uses our custom ASP.NET form for editing information. Also, now, our WF uses this content type for tasks, so when we select “Edit Item” on a task we can see our custom ASP.NET task form (which is not ready to show all the information yet).


Step 3. Adding form logic for showing and completing a task.

The last step is to add controls to our custom ASP.NET task form and make them interact with the workflow.

Pitfall: Ways of interacting with WF which we could use in SP2010 don’t work with SP2013 WFs anymore. Also, today (March 2013) there is the lack of documentation for ways of interacting with the Workflow Manager and it seems nobody (except Workflow Manager development team from Microsoft) knows how to work with it.

Workaround: Tasks activities in its internals use subscribing on item change event to make conclusion if task is completed, so we can change task fields directly and task activity will perform check immediately after that. For instance if we want to reassign our task, we could simply change the “Assigned To” field of the task item.

note: if you want to have a look at internals (XAML) of some activities yourself, you can open table [dbo.Activities] which is located in [WFResourceManagementDB] using SQL Server Management Studio.

1. Open our ASPX form page (MyCustomTaskForm.aspx) in VS and add layout and controls to it.

For that replace all “asp:Content” elements of MyCustomTaskForm.aspx file (don’t touch rows starting with “<%@”) with the following:

<asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
    <style type="text/css">
        .taskInfo {
            width: 500px;
            border: black 2px solid;
            border-collapse: collapse;
        }

        .taskInfo > tbody > tr > td {
            border: black 1px solid;
        }

        .taskInfo td.buttons {
            border-bottom-width: 2px;
        }

        .header {
            color: white;
            background-color: #0071C6;
            font-size: 20px;
            text-align: center;
        }

        .buttons table {
            display: inline;
            vertical-align: bottom;
            width: 20px;
        }

        .field {
            width: 100px;
            background-color: #DDDDDD;
        }

        .fieldVal {
            width: 150px;
        }

        input.approve {
            background-color: #D0EED0;
        }

        input.reject {            
            background-color: #F0D0D0
        }
    </style>
</asp:Content>

<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
    <table class="taskInfo">
        <tr>
            <td class="header" colspan="4">
                <SharePoint:FieldValue ID="FieldValue1" runat="server" FieldName="Task Name" ControlMode="Display" />
            </td>
        </tr>
        <tr>
            <td class="field">Requested by</td>
            <td class="fieldVal">
                <SharePoint:FieldValue ID="FF_CreatedBy" runat="server" FieldName="Created By" ControlMode="Display" />
            </td>
            <td class="field">Due date</td>
            <td class="fieldVal">
                <SharePoint:FieldValue ID="FF_DueDate" runat="server" FieldName="Due Date" ControlMode="Display" />
            </td>
        </tr>
        <tr>
            <td class="field">Task details</td>
            <td class="longFieldVal" colspan="3">
                <SharePoint:FieldValue ID="FF_Body" runat="server" FieldName="Body" ControlMode="Display" />
            </td>
        </tr>
        <tr>
            <td class="buttons" colspan="4">
                        <asp:Button runat="server" ID="ApproveButton" Text="Approve" CssClass="approve" OnClick="ApproveButton_Clicked"/>
                        <asp:Button runat="server" ID="RejectButton" Text="Reject" CssClass="reject" OnClick="RejectButton_Clicked"/>
                        <SharePoint:GoBackButton runat="server" ID="GoBackButtonn" />
            </td>
        </tr>
    </table>
</asp:Content>

<asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
    <SharePoint:FieldValue ID="FF_TaskName1" runat="server" FieldName="Task Name" ControlMode="Display" />
</asp:Content>

<asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">
    <SharePoint:FieldValue ID="FF_TaskName2" runat="server" FieldName="Task Name" ControlMode="Display" />
</asp:Content>

2. Add codebehind for task form to Approve and Reject.

For that press F7 in VS when you are editing MyCustomTaskForm.aspx to see its codebehind.

Image may be NSFW.
Clik here to view.
130309_blog_19

Replace text of the class with the following.

        protected void Page_Load(object sender, EventArgs e)
        {
        }

        protected void ApproveButton_Clicked(object sender, EventArgs e)
        {
            CompleteCurrentTask("Approved");
        }

        protected void RejectButton_Clicked(object sender, EventArgs e)
        {
            CompleteCurrentTask("Rejected");
        }

        private void CompleteCurrentTask(string outcome)
        {
            //Completing a task
            SPContext.Current.Item["TaskOutcome"] = outcome;
            SPContext.Current.Item["PercentComplete"] = "1";
            SPContext.Current.Item["Status"] = "Completed";
            SPContext.Current.Item.Update();

            //Closing the form
            SPUtility.Redirect(string.Empty, SPRedirectFlags.UseSource, Context);
        }

3. Check whether it works.

For that you have to deploy new version of our form (CTRL-F5). After that you could try to edit our task again. You should see the new task form and should be able to complete the task by pressing Approve or Reject buttons.

Image may be NSFW.
Clik here to view.
130312_blog_08

 

Image may be NSFW.
Clik here to view.
130312_blog_09

 

After pressing the Approve button, we could see that our task and workflow completes.

Image may be NSFW.
Clik here to view.
130312_blog_10

 

Hurray!


Conclusion.

During this walkthrough, we have created custom ASP.NET task form for our workflow. This is quite hard to implement (in comparision with the InfoPath task forms). However, this approach has great level of flexibility and you can reuse the most part of your code and styles in it. Frankly speaking, personally, I like this approach much more than custom InfoPath forms. It needs some efforts to implement the first form; however, every another form needs less and less efforts. Also you can easily change the look of all your forms, by changing CSS styles in one place. In addition to that you can implement all the logic that you need. Also you can use jQuery controls and AJAX in this approach. So, this way has almost no limitations! During the other posts I will show you some useful techniques which could help you to like this approach as much as I do. So, stay tuned! Image may be NSFW.
Clik here to view.
:-)

Have a nice day!

Regards, Michael.

PS: If you have some suggestions, ideas, critisism or just want to talk about SharePoint, don’t hesitate to write me a letter or leave a comment. I like to share my knowledge and your feedback helps me to understand that it is useful for you. Also it helps me to improve the quality of the posts. So, don’t shy to leave a feedback even if it is a comment regarding grammar mistakes! Also you can subscribe to updates by clicking the Follow button in the right bottom of the page. Image may be NSFW.
Clik here to view.
:-)


Viewing all articles
Browse latest Browse all 9

Trending Articles