Walkthrough: Deploying a InfoPath 2010 List Form in a Visual Studio 2010 solution package

This is not easy. It took me some days. – Now it works! Smile

Here I’ll show you how to create a List Form for a SharePoint List using InfoPath 2010. Therefore you need SharePoint 2010 Server with Enterprise CALs! – With InfoPath Forms Services it’s possible to render List Forms (“New”, “Edit” and “Display” forms) as browser enabled InfoPath forms. This is really, really cool!

I’ve published the project source code on Codeplex: http://spinfopathlistform.codeplex.com/

Lets start…

1. We create a SharePoint site collection named “http://sharepoint.local/sites/infopathlistform”.

image

2. Now we activate the site collection features:

  • SharePoint Server Enterprise Site Collection features
  • SharePoint Server Standard Site Collection features

image

The enterprise features need to be activated in order to get InfoPath Forms Services working.

3. Open Visual Studio 2010. Create an “Empty SharePoint Project” named “ik.SharePoint2010.InfoPathListFormDemo”.

image

Deploy them as “Farm Solution”.

image

4. Now we add a new project item of type “List Definition” named “Test List 1”.

image

We choose “Custom List” as base type and check “Add a list instance…”

image

5. We open the “Elements.xml” file of the List Instance.

image

We change the List Title and List URL.

image

6.  We edit the “schema.xml” file.

image

We create a list content type with 3 fields.

Here you see the complete content of the “Schema.xml” file.

 <?xml version="1.0" encoding="utf-8"?> 
 <List xmlns:ows="Microsoft SharePoint" Title="Test List 1" FolderCreation="FALSE"
       Direction="$Resources:Direction;"
       Url="Lists/ik.SharePoint2010.InfoPathListFormDemo-TestList1"
       Type="100"
       BaseType="0" xmlns="http://schemas.microsoft.com/sharepoint/"> 
   <MetaData> 
     <ContentTypes> 
       <ContentType ID="0x01009A15733A093E44C385EDB29F8E2E1B5A" Name="List Item" Inherits="false"> 
         <Folder TargetName="Item" /> 
         <FieldRefs> 
           <FieldRef ID="{10F8137D-B555-472C-8ACB-B64FF5BEAAF8}" Name="Field_1" /> 
           <FieldRef ID="{84E33CDB-8DDC-4F46-BBF5-845D4071ED41}" Name="Field_2" /> 
           <FieldRef ID="{52680EED-BE6F-478F-A6EC-730398CD626C}" Name="Field_3" /> 
         </FieldRefs> 
       </ContentType> 
       <ContentTypeRef ID="0x0120" /> 
     </ContentTypes> 
     <Fields> 
       <Field ID="{10F8137D-B555-472C-8ACB-B64FF5BEAAF8}" Name="Field_1" StaticName="Field_1"
              DisplayName="Text Field" Type="Text"/> 
       <Field ID="{84E33CDB-8DDC-4F46-BBF5-845D4071ED41}" Name="Field_2"  StaticName="Field_2"
              DisplayName="DateTime Field" Type="DateTime" Format="DateOnly" /> 
       <Field ID="{52680EED-BE6F-478F-A6EC-730398CD626C}" Name="Field_3"  StaticName="Field_3"
              DisplayName="Checkbox Field" Type="Boolean" /> 
     </Fields> 
     <Views> 
       <View BaseViewID="0" Type="HTML" MobileView="TRUE" TabularView="FALSE"> 
         <Toolbar Type="Standard" /> 
         <XslLink Default="TRUE">main.xsl</XslLink> 
         <RowLimit Paged="TRUE">30</RowLimit> 
         <ViewFields> 
           <FieldRef Name="LinkTitleNoMenu"></FieldRef> 
           <FieldRef Name="Field_1"></FieldRef> 
           <FieldRef Name="Field_2"></FieldRef> 
           <FieldRef Name="Field_3"></FieldRef> 
         </ViewFields> 
         <Query> 
           <OrderBy> 
             <FieldRef Name="Modified" Ascending="FALSE"></FieldRef> 
           </OrderBy> 
         </Query> 
         <ParameterBindings> 
           <ParameterBinding Name="AddNewAnnouncement" Location="Resource(wss,addnewitem)" /> 
           <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" /> 
           <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_ONET_HOME)" /> 
         </ParameterBindings> 
       </View> 
       <View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" Url="AllItems.aspx"> 
         <Toolbar Type="Standard" /> 
         <XslLink Default="TRUE">main.xsl</XslLink> 
         <RowLimit Paged="TRUE">30</RowLimit> 
         <ViewFields> 
           <FieldRef Name="Attachments"></FieldRef> 
           <FieldRef Name="LinkTitle"></FieldRef> 
           <FieldRef Name="Field_1"></FieldRef> 
           <FieldRef Name="Field_2"></FieldRef> 
           <FieldRef Name="Field_3"></FieldRef> 
         </ViewFields> 
         <Query> 
           <OrderBy> 
             <FieldRef Name="ID"></FieldRef> 
           </OrderBy> 
         </Query> 
         <ParameterBindings> 
           <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" /> 
           <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_DEFAULT)" /> 
         </ParameterBindings> 
       </View> 
     </Views> 
     <Forms> 
       <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pagesform.aspx" WebPartZoneID="Main" /> 
       <Form Type="EditForm" Url="EditForm.aspx" SetupPath="pagesform.aspx" WebPartZoneID="Main" /> 
       <Form Type="NewForm" Url="NewForm.aspx" SetupPath="pagesform.aspx" WebPartZoneID="Main" /> 
     </Forms> 
   </MetaData> 
 </List>

 

7. The next step is to add an “Empty Element” project item named “Fields”. We add the following content:

 <?xml version="1.0" encoding="utf-8"?> 
 <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> 
   <Field ID="{10F8137D-B555-472C-8ACB-B64FF5BEAAF8}" Name="Field_1" StaticName="Field_1"
          DisplayName="Text Field" Type="Text"/> 
   <Field ID="{84E33CDB-8DDC-4F46-BBF5-845D4071ED41}" Name="Field_2"  StaticName="Field_2"
          DisplayName="DateTime Field" Type="DateTime" Format="DateOnly" /> 
   <Field ID="{52680EED-BE6F-478F-A6EC-730398CD626C}" Name="Field_3"  StaticName="Field_3"
          DisplayName="Checkbox Field" Type="Boolean" /> 
 </Elements> 


 

8. Now we deploy the project.

9. Open the site in the browser. Navigate to the “Test List 1”. Select “Edit in SharePoint Designer” from the “Site Actions” menu.

image

10. In SharePoint Designer 2010 open the “Lists and Libraries” from the “Navigation” pane and open the “Test List 1”.

image

In the Ribbon you’ll see the command “Design Forms in InfoPath”.

image

Click the command button and select “List Item” in the drop down menu.

Now InfoPath Designer 2010 opens…

11. In InfoPath Designer 2010 modify the form.

(I will not modify it.)

image

Press the “Publish” button on the Shortcut Menu:

image

12. In SharePoint Designer 2010 choose “All Files” from the “Navigation” pane. Click “Lists”.

image

Click “TestList1”.

image

Click “Item”.

image

Right-click “template.xsn”. Select “Properties…” from the context menu.

image

Select the “Location” from the properties dialog.

image

Copy the URL and open it in a new browser window. You’ll get a “File Download” dialog.

image

Save the file to a temporary location, e.g. to the Desktop.

13. Add a new “Module” project item and name it “Form”.

image

Open a Windows Explorer. Navigate to the Desktop. Drag the file “template.xsn” from the Desktop into the “Form” module inside the Visual Studio project.

Modify the “Elements.xml” file of the “Form” module.

image

14. Add a new “Module” project item and name it “FormPages”.

Into the “Elements.xml” file of this module enter the following code:

 

 <?xml version="1.0" encoding="utf-8"?> 
 <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> 
   <Module Name="TestList1Form" Url="Lists/TestList1/Item" SetupPath="pages" RootWebOnly="FALSE" xmlns="http://schemas.microsoft.com/sharepoint/"> 
     <File Url="displayifs.aspx" Type="Ghostable" Path="form.aspx"> 
       <BinarySerializedWebPart> 
         <GUIDMap> 
           <GUID Id="1b8faa0c_4e13_43e7_981f_57d525170d09" ListUrl="Lists/TestList1" /> 
         </GUIDMap> 
         <WebPart ID="{D95DEC48-6F9E-4961-BE47-380AD2870CCA}"
                  List="{$ListId:Lists/TestList1;}"
                  Type="4"
                  Url="Lists/TestList1/Item/displayifs.aspx"
                  WebPartOrder="0"
                  WebPartZoneID="Main"
                  IsIncluded="True"
                  FrameState="0"
                  WPTypeId="{b1dc92e2-8558-f555-ae81-35ed9ddf1644}"
                  Assembly="Microsoft.Office.InfoPath.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
                  Class="Microsoft.Office.InfoPath.Server.Controls.WebUI.BrowserFormWebPart"
                  AllUsers="B6Dt/iwAAAABAAAAAAAAAAEAAAB+bGlzdC9JdGVtL3RlbXBsYXRlLnhzbgD/ARQrABQCAgIDAgMBBAACAQIJAQEAAggFDEZvcm1Mb2NhdGlvbgUXfmxpc3QvSXRlbS90ZW1wbGF0ZS54c24FDUNvbnRlbnRUeXBlSWQFJjB4MDEwMDdEMTVFNzgxOUUwNDMzNEE4QkY5OTE3OEM1OUNDNjhDBQxMaXN0Rm9ybU1vZGULKaIBTWljcm9zb2Z0Lk9mZmljZS5JbmZvUGF0aC5TZXJ2ZXIuQ29udHJvbHMuV2ViVUkuTGlzdEZvcm1Nb2RlLCBNaWNyb3NvZnQuT2ZmaWNlLkluZm9QYXRoLlNlcnZlciwgVmVyc2lvbj0xNC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj03MWU5YmNlMTExZTk0MjljAQUOU3VibWl0QmVoYXZpb3ILKaQBTWljcm9zb2Z0Lk9mZmljZS5JbmZvUGF0aC5TZXJ2ZXIuQ29udHJvbHMuV2ViVUkuU3VibWl0QmVoYXZpb3IsIE1pY3Jvc29mdC5PZmZpY2UuSW5mb1BhdGguU2VydmVyLCBWZXJzaW9uPTE0LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPTcxZTliY2UxMTFlOTQyOWMDAQAAAgICAgU+VXNlIHRoaXMgV2ViIFBhcnQgdG8gZGlzcGxheSBhbiBJbmZvUGF0aCBicm93c2VyLWVuYWJsZWQgZm9ybS4="
                  PerUser="/wEUKwAJAgICAwIBAQAAAgQChAELKjFTeXN0ZW0uV2ViLlVJLldlYkNvbnRyb2xzLldlYlBhcnRzLlBhcnRDaHJvbWVUeXBlAgIEBRZJbmZvUGF0aCBGb3JtIFdlYiBQYXJ0" /> 
       </BinarySerializedWebPart> 
     </File> 
     <File Url="editifs.aspx" Type="Ghostable" Path="form.aspx"> 
       <BinarySerializedWebPart> 
         <GUIDMap> 
           <GUID Id="1b8faa0c_4e13_43e7_981f_57d525170d09" ListUrl="Lists/TestList1" /> 
         </GUIDMap> 
         <WebPart ID="{f811e526-1ad2-4563-b51b-4233f2641a33}"
                  List="{$ListId:Lists/TestList1;}"
                  Type="6"
                  Flags="0"
                  Url="Lists/TestList1/Item/editifs.aspx"
                  WebPartOrder="0"
                  WebPartZoneID="Main"
                  IsIncluded="True"
                  FrameState="0"
                  WPTypeId="{b1dc92e2-8558-f555-ae81-35ed9ddf1644}"
                  Assembly="Microsoft.Office.InfoPath.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
                  Class="Microsoft.Office.InfoPath.Server.Controls.WebUI.BrowserFormWebPart"
                  AllUsers="B6Dt/iwAAAABAAAAAAAAAAEAAAB+bGlzdC9JdGVtL3RlbXBsYXRlLnhzbgD/ARQrABICAgIDAgMBBAACAQIJAQEAAgYFDEZvcm1Mb2NhdGlvbgUXfmxpc3QvSXRlbS90ZW1wbGF0ZS54c24FDUNvbnRlbnRUeXBlSWQFJjB4MDEwMDdEMTVFNzgxOUUwNDMzNEE4QkY5OTE3OEM1OUNDNjhDBQ5TdWJtaXRCZWhhdmlvcgsppAFNaWNyb3NvZnQuT2ZmaWNlLkluZm9QYXRoLlNlcnZlci5Db250cm9scy5XZWJVSS5TdWJtaXRCZWhhdmlvciwgTWljcm9zb2Z0Lk9mZmljZS5JbmZvUGF0aC5TZXJ2ZXIsIFZlcnNpb249MTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49NzFlOWJjZTExMWU5NDI5YwMBAAACAgICBT5Vc2UgdGhpcyBXZWIgUGFydCB0byBkaXNwbGF5IGFuIEluZm9QYXRoIGJyb3dzZXItZW5hYmxlZCBmb3JtLg=="
                  PerUser="/wEUKwAJAgICAwIBAQAAAgQChAELKjFTeXN0ZW0uV2ViLlVJLldlYkNvbnRyb2xzLldlYlBhcnRzLlBhcnRDaHJvbWVUeXBlAgIEBRZJbmZvUGF0aCBGb3JtIFdlYiBQYXJ0" /> 
       </BinarySerializedWebPart> 
     </File> 
     <File Url="newifs.aspx" Type="Ghostable" Path="form.aspx"> 
       <BinarySerializedWebPart> 
         <GUIDMap> 
           <GUID Id="1b8faa0c_4e13_43e7_981f_57d525170d09" ListUrl="Lists/TestList1" /> 
         </GUIDMap> 
         <WebPart ID="{7319002a-a547-4cdf-8acc-c5ba9cf8a6c9}"
                  List="{$ListId:Lists/TestList1;}"
                  Type="8"
                  Flags="0"
                  Url="Lists/TestList1/Item/newifs.aspx"
                  WebPartOrder="0"
                  WebPartZoneID="Main"
                  IsIncluded="True"
                  FrameState="0"
                  WPTypeId="{b1dc92e2-8558-f555-ae81-35ed9ddf1644}"
                  Assembly="Microsoft.Office.InfoPath.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
                  Class="Microsoft.Office.InfoPath.Server.Controls.WebUI.BrowserFormWebPart"
                  AllUsers="B6Dt/iwAAAABAAAAAAAAAAEAAAB+bGlzdC9JdGVtL3RlbXBsYXRlLnhzbgD/ARQrABICAgIDAgMBBAACAQIJAQEAAgYFDEZvcm1Mb2NhdGlvbgUXfmxpc3QvSXRlbS90ZW1wbGF0ZS54c24FDUNvbnRlbnRUeXBlSWQFJjB4MDEwMDdEMTVFNzgxOUUwNDMzNEE4QkY5OTE3OEM1OUNDNjhDBQ5TdWJtaXRCZWhhdmlvcgsppAFNaWNyb3NvZnQuT2ZmaWNlLkluZm9QYXRoLlNlcnZlci5Db250cm9scy5XZWJVSS5TdWJtaXRCZWhhdmlvciwgTWljcm9zb2Z0Lk9mZmljZS5JbmZvUGF0aC5TZXJ2ZXIsIFZlcnNpb249MTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49NzFlOWJjZTExMWU5NDI5YwMBAAACAgICBT5Vc2UgdGhpcyBXZWIgUGFydCB0byBkaXNwbGF5IGFuIEluZm9QYXRoIGJyb3dzZXItZW5hYmxlZCBmb3JtLg=="
                  PerUser="/wEUKwAJAgICAwIBAQAAAgQChAELKjFTeXN0ZW0uV2ViLlVJLldlYkNvbnRyb2xzLldlYlBhcnRzLlBhcnRDaHJvbWVUeXBlAgIEBRZJbmZvUGF0aCBGb3JtIFdlYiBQYXJ0" /> 
       </BinarySerializedWebPart> 
     </File> 
   </Module> 
 </Elements>

 

During deployment this creates the form aspx pages that will host the InfoPath Web Part that renders the form at runtime.

In the XML code there are several references to the destination list. All of them have to be set to “Lists/TestList1”. All the code needs to remain unmodified. Don’t change “WPTypeId” attributes! “{b1dc92e2-8558-f555-ae81-35ed9ddf1644}” is the identifier for InfoPath Render Web Part.

BUT change the “ID” attributes of the three “WebPart” tags! Use the “Create GUID” tool from the “Tools” menu of Visual Studio 2010.

15. Now open the “Schema.xml” file of the List Definition project item of “Test List 1”. Add the following code at the before the closing tag of our list content type.

         <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"> 
               <Display> ~list/Item/displayifs.aspx</Display> 
               <Edit> ~list/Item/editifs.aspx</Edit> 
               <New> ~list/Item/newifs.aspx</New> 
             </FormUrls> 
           </XmlDocument> 
         </XmlDocuments>

 

16. Add another project item of type “Empty Element” named “PropertyBag”. Edit the “Elements.xml” file. Add this code:

 <?xml version="1.0" encoding="utf-8"?> 
 <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> 
   <PropertyBag Url="Lists/TestList1/Item/template.xsn"  
                ParentType="File" RootWebOnly="FALSE"  
                xmlns="http://schemas.microsoft.com/sharepoint/"> 
     <Property Name="ipfs_listform" Value="true" Type="string" /> 
     <Property Name="ipfs_streamhash" Value="" Type="string" /> 
   </PropertyBag> 
 </Elements> 

 

This will define the “template.xsn” to be a “InfoPath Forms Services” file (image).

17. Deploy the project.

18. Open the browser and navigate to the “Test List 1”.

Click “Add new item”…

19. HERE WE ARE!

image

But if you enter values and try to save you get this error:

image

This is caused by the missing “Title” field inside the form. This field is marked as mandatory so you need to define it or to remove it from the Content Type and modify the form.

We will do the last one now.

20. In Visual Studio modify the “schema.xml” file of the “Test List 1”. Insert the marked line of code inside the “FieldsRefs” tag of the content type with id starting “0x01…”.

image

Now search for “LinkTitleNoMenu” in the schema.xml file. Replace this “view field reference” with “Edit”.

Now search for “LinkTitle” and replace it with “Edit” too.

21. In Visual Studio look for “template.xsn” in “Form” path in the Solution Explorer. Right-Click the project item and select “Open Containing Folder”.

image

22. In Windows Explorer right-click the file “template.xsn” and click “Design”. The InfoPath 2010 Designer will open.

23. In InfoPath 2010 you’ll see that “Title” cannot be removed. To remove it you would need the edit the xsn file with Notepad: XSN is a CAB file. So you can rename it to cab, extract it’s content, modify the “manifest.xfs” file and compress the folder as CAB file named “template.xsn”… (If you need assistance on this please post as comment.)

In the “Fields” pane select “Title”.

image

(This is the “advanced view” !)

Click the arrow behind the element. Click “Properties” in the context menu.

Uncheck “Cannot be blank”. Click the “OK” button. Save the file. Don’t press “Publish” on the upcoming dialog. Just press “Save”!

Quit InfoPath.

Deploy the project.

24. In Internet Explorer refresh you site and add a new item to the “Test  List 1”.

You’ll see: the “Title” column is gone. Now we have a “Edit item” column on the list view.

Now add an item.

image

Save it.

25. HERE WE ARE AGAIN!

It works for me now!

image

Just for testing purpose select the list item and click “View Item” on the Ribbon.

You will see the list item in a read-only InfoPath browser form!! – If you click “Edit” on the Ribbon, you’ll be able to edit the item.

Walkthrough: Creating a simple Sequential Workflow with a custom Task Form in SharePoint 2010 using Visual Studio 2010 (Part 1 of 2)

In this walkthrough I want to show you how to create a Sequential Workflow with Visual Studio 2010 for use in SharePoint 2010. – I will show how to create a custom Task Form for interaction with users. The Task form will be a native SharePoint list form. No InfoPath. There are many InfoPath samples out there but they cannot be used on a SharePoint Foundation 2010 platform. But workflows can be used on SharePoint Foundation 2010 too!

To reproduce the following steps you need to create a SharePoint site. – In the walkthrough I’ll use a Site Collection located at “http://sharepoint.local/sites/workflow”.

This blog post is part 1 of 2. It describes the steps 1 to 15. Read part 2 here: https://blog.kenaro.com/2011/03/30/walkthrough-creating-a-simple-sequential-workflow-with-a-custom-task-form-in-sharepoint-2010-using-visual-studio-2010-part-2-of-2/

You can download – and help to develop – the whole demo project source code at Codeplex: http://spworkflowdemo.codeplex.com/

(If you need assistance for the deployment process because of deployment errors please see this third post of this series: https://blog.kenaro.com/2011/04/22/walkthrough-creating-a-simple-sequential-workflow-with-a-custom-task-form-in-sharepoint-2010-using-visual-studio-2010-part-3-of-21/)

Let’s start…

1. We create the Site Collection. Use the “Blank Site” site template.

image

2. In Visual Studio 2010 we create a Empty SharePoint Project. I named it “ik.SharePoint2010.Workflow”

image

We create it with “Deploy as farm solution” and specify the location “http://sharepoint.local/sites/workflow/”.

image

3. This is the project structure at start:

image

4. First we need to create an instance of the Workflow History list that is needed for the workflow.

Create a new “Empty Element” project item named “Workflow History”.

image

Open the created “element.xml” file and modify it as shown below.

1: <?xml version="1.0" encoding="utf-8"?>
2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
3:  <ListInstance Title="Workflow History"
4:  OnQuickLaunch="TRUE"
5:  TemplateType="140"
6:  FeatureId="00BFEA71-4EA5-48D4-A4AD-305CF7030140"
7:  Url="Lists/WorkflowHistory"
8:  Description="">
9:  </ListInstance>
10: </Elements>

The “TemplateType” attribute represents the “Workflow History” list template. It resists on a SharePoint feature with ID “00BFEA71-4EA5-48D4-A4AD-305CF7030140”. It’s a native SharePoint feature.

You can add the attibute “Hidden” to the “ListInstance” tag and set it’s value to “TRUE” to hide the list as it’s done by SharePoint by default for this list. In this case you should also change “OnQuickLaunch” to “FALSE”. For my demo purpose I want to have “Workflow History” visible and on the Quick Launch bar.

5. Now we will create all tools we need for a “Workflow 1”. (May be I’ll create more workflow demos later. So it’s number 1.)

6. We create the SharePoint fields for “Workflow 1”. Therefore we create another “Empty Element” project item named “Workflow 1 Fields”.

image

I’ll create 3 fields for use in the Task Form we will create: Test1, Test2, Test3. They are all fields of type Text.

1: <?xml version="1.0" encoding="utf-8"?>
2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
3:  <!-- Fields for Task 1 of Workflow 1-->
4:  <Field ID="{2FE15855-3CAB-44A6-AB29-1600204FCA20}" Name="Workflow1Task1_Test1"
5:  MaxLength="255" DisplayName="Test1" Description=""
6:  Direction="None" Type="Text" Overwrite="TRUE"
7:  xmlns="http://schemas.microsoft.com/sharepoint/" />
8:  <Field ID="{517B22A5-1B89-4C24-82BE-3D4FD99645BC}" Name="Workflow1Task1_Test2"
9:  MaxLength="255" DisplayName="Test2" Description=""
10:  Direction="None" Type="Text" Overwrite="TRUE"
11:  xmlns="http://schemas.microsoft.com/sharepoint/" />
12:  <Field ID="{3ECFF1FE-F56B-4556-8805-4570D9422FF4}" Name="Workflow1Task1_Test3"
13:  MaxLength="255" DisplayName="Test3" Description=""
14:  Direction="None" Type="Text" Overwrite="TRUE"
15:  xmlns="http://schemas.microsoft.com/sharepoint/" />
16: </Elements>

7. Now we create a new “Module” project item named “Workflow 1 Forms”. In this module we will store the Task Form.

image

Remove the “Sample.txt” file from the created module.

Create a new “Application Page” project item named “Task1Form.aspx”.

image

This project item will stored in the folder “Layoutsik.SharePoint2010.Workflow”.

image

Move the project item “Task1Form.aspx” using Drag & Drop into the module “Workflow 1 Forms”.

image

Remove the “Layouts” folder from the project. It should be empty.

8. We open “Task1Form.aspx”

First we need to edit the “Page” tag of the ASPX site.

1:  <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Task1Form.aspx.cs" Inherits="ik.SharePoint2010.Workflow.Task1Form" MasterPageFile="~masterurl/default.master"  %>

Now we insert the following code into the “PlaceHolderMain” content placeholder.

1:     <asp:ScriptManagerProxy runat="server" ID="ProxyScriptManager">
2:     </asp:ScriptManagerProxy>
3:     <table width="100%" border="0" cellpadding="0" cellspacing="0">
4:         <tr>
5:             <td valign="top">
6:                 <table cellspacing="0" cellpadding="4" border="0" width="100%">
7:                     <tr>
8:                         <td class="ms-vb">
9:                             &nbsp;
10:                         </td>
11:                     </tr>
12:                 </table>
13:                 <table border="0" width="100%">
14:                     <tr>
15:                         <td>
16:                             <table border="0" cellspacing="0" width="100%">
17:                                 <tr>
18:                                     <td class="ms-formlabel" valign="top" nowrap="true" width="25%">
19:                                         <b>Title:</b>
20:                                     </td>
21:                                     <td class="ms-formbody" valign="top" width="75%">
22:                                         <SharePoint:FormField runat="server" ID="ff4" ControlMode="Display" FieldName="Title" /><br />
23:                                     </td>
24:                                 </tr>
25:                                 <tr>
26:                                     <td width="25%" class="ms-formlabel">
27:                                         <b>Test1:</b>
28:                                     </td>
29:                                     <td width="75%" class="ms-formbody">
30:                                         <SharePoint:FormField runat="server" ID="ff1" ControlMode="Edit" FieldName="Workflow1Task1_Test1" />
31:                                         <SharePoint:FieldDescription runat="server" ID="ff1description" FieldName="Workflow1Task1_Test1"
32:                                             ControlMode="Edit" />
33:                                     </td>
34:                                 </tr>
35:                                 <tr>
36:                                     <td width="25%" class="ms-formlabel">
37:                                         <b>Test2:</b>
38:                                     </td>
39:                                     <td width="75%" class="ms-formbody">
40:                                         <SharePoint:FormField runat="server" ID="ff2" ControlMode="Edit" FieldName="Workflow1Task1_Test2" />
41:                                         <SharePoint:FieldDescription runat="server" ID="ff2description" FieldName="Workflow1Task1_Test2"
42:                                             ControlMode="Edit" />
43:                                     </td>
44:                                 </tr>
45:                                 <tr>
46:                                     <td width="25%" class="ms-formlabel">
47:                                         <b>Test3:</b>
48:                                     </td>
49:                                     <td width="75%" class="ms-formbody">
50:                                         <SharePoint:FormField runat="server" ID="ff3" ControlMode="Edit" FieldName="Workflow1Task1_Test3" />
51:                                         <SharePoint:FieldDescription runat="server" ID="ff3description" FieldName="Workflow1Task1_Test3"
52:                                             ControlMode="Edit" />
53:                                     </td>
54:                                 </tr>
55:                             </table>
56:                         </td>
57:                     </tr>
58:                 </table>
59:                 <table cellspacing="0" cellpadding="4" border="0" width="100%">
60:                     <tr>
61:                         <td nowrap="nowrap" class="ms-vb">
62:                             <asp:Button Text="Save As Draft" runat="server" ID="btnSaveAsDraft" />
63:                         </td>
64:                         <td>
65:                             <asp:Button Text="Complete Task" runat="server" ID="btnComplete" />
66:                         </td>
67:                         <td nowrap="nowrap" class="ms-vb" width="99%">
68:                             <asp:Button Text="Cancel" runat="server" ID="btnCancel" />
69:                         </td>
70:                     </tr>
71:                 </table>
72:             </td>
73:             <td width="1%" class="ms-vb" valign="top">&nbsp;</td>
74:         </tr>
75:     </table>
76:

Now we add some ASP.NET code into the “PlaceHolderPageTitle” content placeholder.

1:     <SharePoint:ListFormPageTitle runat="server" />

Furthermore we add this lines of code into the “PlaceHolderPageTitleInTitleArea” content placeholder.

1:     <span class="die">
2:         <SharePoint:ListProperty Property="LinkTitle" runat="server" ID="ID_LinkTitle" />
3:         : </span>
4:     <SharePoint:ListItemProperty ID="ID_ItemProperty" MaxLength="40" runat="server" />

At least we add the following code into the “PlaceHolderAdditionalPageHead” content placeholder.

1:     <SharePoint:UIVersionedContent UIVersion="4" runat="server">
2:         <contenttemplate>
3:             <SharePoint:CssRegistration Name="forms.css" runat="server"/>
4:         </contenttemplate>
5:     </SharePoint:UIVersionedContent>

You can see the input fields for the three fields of Task 1. Furthermore you see three buttons. For them we now create some “code behind”.

1: using System;
2: using Microsoft.SharePoint;
3: using Microsoft.SharePoint.WebControls;
4: using Microsoft.SharePoint.Utilities; 
5:
6: namespace ik.SharePoint2010.Workflow
7: {
8:     public partial class Task1Form : WebPartPage
9:     {
10:         protected void Page_Load(object sender, EventArgs e)
11:         {
12:             btnSaveAsDraft.Click += new EventHandler (btnSaveAsDraft_Click);
13:             btnComplete.Click += new EventHandler (btnComplete_Click);
14:             btnCancel.Click += new EventHandler (btnCancel_Click);
15:         }
16:
17:         void btnCancel_Click(object sender, EventArgs e)
18:         {
19:             CloseForm();
20:         }
21:
22:         private void CloseForm()
23:         {
24:             if ( ( SPContext.Current != null ) && SPContext.Current.IsPopUI )
25:             {
26:                 this.Context.Response.Write("<script>window.frameElement.commitPopup();</script>" );
27:                 this.Context.Response.Flush();
28:                 this.Context.Response.End();
29:             }
30:             else
31:             {
32:                 string str = this.Page.Request.QueryString["Source"];
33:                 if ( ( str != null ) && ( str.Length > 0 ) )
34:                 {
35:                     SPUtility.Redirect(string.Empty, SPRedirectFlags.UseSource, this.Context);
36:                 }
37:             }
38:         }
39:
40:         void btnComplete_Click(object sender, EventArgs e)
41:         {
42:             SPList l = SPContext.Current.List;
43:             SPListItem li = SPContext.Current.ListItem;
44:             li[SPBuiltInFieldId.TaskStatus] = "Tasks_Completed";
45:             li[SPBuiltInFieldId.PercentComplete] = 1;
46:
47:             SaveButton.SaveItem(SPContext.Current, false, "" );
48:
49:             CloseForm();
50:         }
51:
52:         void btnSaveAsDraft_Click(object sender, EventArgs e)
53:         {
54:             SaveButton.SaveItem(SPContext.Current, false, "" );
55:
56:             CloseForm();
57:         }
58:     }
59: }

We need to modify the “Elements.xml” file of the module named “Workflow 1 Forms”.

1: <?xml version="1.0" encoding="utf-8"?>
2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
3:  <Module Name="Workflow 1 Forms" Url="Workflow1Forms" RootWebOnly="FALSE">
4:  <File Path="Workflow 1 FormsTask1Form.aspx" Url="Task1Form.aspx" />
5:  </Module>
6: </Elements> 

This specifies there to store the “Task1Form.aspx” file in the site structure.

9. In the next step we create the task list that will contain our workflow tasks.

First create a “List Definition” project item named “Workflow 1 Tasks”.

image

Use “Workflow 1 Tasks” as name of the list definition and “Tasks” as base type. Check “Add a list instance…”.

image

10. Now open “Elements.xml” of the new list definition project item.

image

We need to change the identifier of the list type we create! – It must be “107”. This is the list template ID for workflow tasks lists in SharePoint. The workflow designer will search for a list with this type inside the site where a new workflow will be created.

Here is the content of “Elements.xml” after our modification:

1: <?xml version="1.0" encoding="utf-8"?>
2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
3:  <ListTemplate
4:  Name="Workflow 1 Tasks"
5:  Type="107"
6:  BaseType="0"
7:  OnQuickLaunch="TRUE"
8:  SecurityBits="11"
9:  Sequence="360"
10:  DisplayName="Workflow 1 Tasks"
11:  Description="Tasks of Workflow 1"
12:  Image="/_layouts/images/itgen.png"/>
13: </Elements>  

11. Now we modify the “Elements.xml” file of the list instance that will be created during deployment:

image

Here we also need to modify the type identifier to “107”. Furthermore we change the list url: “Lists/Workflow1Tasks”.

Here is the complete content of “Elements.xml”:

1: <?xml version="1.0" encoding="utf-8"?>
2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
3:  <ListInstance Title="Workflow 1 Tasks"
4:  OnQuickLaunch="TRUE"
5:  TemplateType="107"
6:  Url="Lists/Workflow1Tasks"
7:  Description="Tasks of Workflow 1">
8:  </ListInstance>
9: </Elements> 

In a “real world” scenario we would prevent the list from being listed on the Quick Launch bar. So the corresponding parameter must be set to “FALSE”.

12. Now we need to modify the “Schema.xml” file of the list definition.

image

First we set the list type to “107” and configure some other attributes:

1: <List xmlns:ows="Microsoft SharePoint" Title="Workflow 1 Tasks"
2:  FolderCreation="FALSE" Direction="$Resources:Direction;"
3:  EnableContentTypes="TRUE" VersioningEnabled="TRUE"
4:  Url="Lists/Workflow1Tasks"
5:  Type="107" BaseType="0"
6:  xmlns="http://schemas.microsoft.com/sharepoint/">
7: […]

Now remove the the content types defined in the “ContentTypes” tag in the “schema.xml” file.

image

Insert this content type definition into the “ContentTypes” tag:

1:  <ContentType ID="0x01080100FFbc98c2529347a5886b8d2576b954ef"
2:  Name="Workflow 1 Tasks 1"
3:  Group="Workflow 1 Tasks"
4:  Description="Content Type of Tasks 1 of Workflow 1">
5:  <FieldRefs>
6:  <FieldRef ID="{2FE15855-3CAB-44A6-AB29-1600204FCA20}" Name="Workflow1Task1_Test1" DisplayName="Test1" Required="FALSE" Hidden="FALSE" ReadOnly="FALSE" PITarget="" PrimaryPITarget="" PIAttribute="" PrimaryPIAttribute="" Aggregation="" Node="" />
7:  <FieldRef ID="{517B22A5-1B89-4C24-82BE-3D4FD99645BC}" Name="Workflow1Task1_Test2" DisplayName="Test2" Required="FALSE" Hidden="FALSE" ReadOnly="FALSE" PITarget="" PrimaryPITarget="" PIAttribute="" PrimaryPIAttribute="" Aggregation="" Node="" />
8:  <FieldRef ID="{3ECFF1FE-F56B-4556-8805-4570D9422FF4}" Name="Workflow1Task1_Test3" DisplayName="Test3" Required="FALSE" Hidden="FALSE" ReadOnly="FALSE" PITarget="" PrimaryPITarget="" PIAttribute="" PrimaryPIAttribute="" Aggregation="" Node="" />
9:
10:  <FieldRef ID="{c042a256-787d-4a6f-8a8a-cf6ab767f12d}" Name="ContentType" />
11:  <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" Required="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE" />
12:  <FieldRef ID="{c3a92d97-2b77-4a25-9698-3ab54874bc6f}" Name="Predecessors" />
13:  <FieldRef ID="{a8eb573e-9e11-481a-a8c9-1104a54b2fbd}" Name="Priority" />
14:  <FieldRef ID="{c15b34c3-ce7d-490a-b133-3f4de8801b76}" Name="Status" />
15:  <FieldRef ID="{d2311440-1ed6-46ea-b46d-daa643dc3886}" Name="PercentComplete" />
16:  <FieldRef ID="{53101f38-dd2e-458c-b245-0c236cc13d1a}" Name="AssignedTo" />
17:  <FieldRef ID="{7662cd2c-f069-4dba-9e35-082cf976e170}" Name="Body" />
18:  <FieldRef ID="{64cd368d-2f95-4bfc-a1f9-8d4324ecb007}" Name="StartDate" />
19:  <FieldRef ID="{cd21b4c2-6841-4f9e-a23a-738a65f99889}" Name="DueDate" />
20:  <FieldRef ID="{58ddda52-c2a3-4650-9178-3bbc1f6e36da}" Name="WorkflowLink" />
21:  <FieldRef ID="{16b6952f-3ce6-45e0-8f4e-42dac6e12441}" Name="OffsiteParticipant" />
22:  <FieldRef ID="{4a799ba5-f449-4796-b43e-aa5186c3c414}" Name="OffsiteParticipantReason" />
23:  <FieldRef ID="{18e1c6fa-ae37-4102-890a-cfb0974ef494}" Name="WorkflowOutcome" />
24:  <FieldRef ID="{e506d6ca-c2da-4164-b858-306f1c41c9ec}" Name="WorkflowName" />
25:  <FieldRef ID="{ae069f25-3ac2-4256-b9c3-15dbc15da0e0}" Name="GUID" />
26:  <FieldRef ID="{8d96aa48-9dff-46cf-8538-84c747ffa877}" Name="TaskType" />
27:  <FieldRef ID="{17ca3a22-fdfe-46eb-99b5-9646baed3f16}" Name="FormURN" />
28:  <FieldRef ID="{78eae64a-f5f2-49af-b416-3247b76f46a1}" Name="FormData" />
29:  <FieldRef ID="{8cbb9252-1035-4156-9c35-f54e9056c65a}" Name="EmailBody" />
30:  <FieldRef ID="{47f68c3b-8930-406f-bde2-4a8c669ee87c}" Name="HasCustomEmailBody" />
31:  <FieldRef ID="{cb2413f2-7de9-4afc-8587-1ca3f563f624}" Name="SendEmailNotification" />
32:  <FieldRef ID="{4d2444c2-0e97-476c-a2a3-e9e4a9c73009}" Name="PendingModTime" />
33:  <FieldRef ID="{35363960-d998-4aad-b7e8-058dfe2c669e}" Name="Completed" />
34:  <FieldRef ID="{1bfee788-69b7-4765-b109-d4d9c31d1ac1}" Name="WorkflowListId" />
35:  <FieldRef ID="{8e234c69-02b0-42d9-8046-d5f49bf0174f}" Name="WorkflowItemId" />
36:  <FieldRef ID="{1c5518e2-1e99-49fe-bfc6-1a8de3ba16e2}" Name="ExtendedProperties" />
37:  </FieldRefs>
38:  <XmlDocuments>
39:  <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
40:  <FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
41:  <Display>ListForm</Display>
42:  <Edit>ListForm</Edit>
43:  <New>ListForm</New>
44:  </FormTemplates>
45:  </XmlDocument>
46:  <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
47:  <FormUrls xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url">
48:  <Edit>Workflow1Forms/Task1Form.aspx</Edit>
49:  </FormUrls>
50:  </XmlDocument>
51:  </XmlDocuments>
52:  </ContentType>
53:
54:

You see the “FormUrls” tag? Inside this tag we specify our custom form template we created before.

The new content type is derived from the “Workflow Task” content type 0x010801. – In the “FieldRefs” section we add our fields we need inside the workflow.

13. Now we need to add the field definitions of our custom fields to the “Schema.xml”. Copy them from the “Elements.xml”  file of project item “Workflow 1 Fields” into the “Fields” tag of “Schema.xml”:

image

Furthermore you need to add a field definition for the field “Completed”:

1:  <Field ID="{35363960-D998-4aad-B7E8-058DFE2C669E}" Name="Completed"
2:  SourceID="http://schemas.microsoft.com/sharepoint/v3"
3:  StaticName="Completed" Group="Base Columns" Type="Boolean"
4:  DisplayName="Completed" Hidden="TRUE" Sealed="TRUE"
5:  Overwrite="TRUE" xmlns="http://schemas.microsoft.com/sharepoint/">
6:  <Default>FALSE</Default>
7:  </Field> 

14. Now deploy the project.

While deployment you may get this dialog:

image

Check “Do not prompt…”. Press “Resolve Automatically”  – it’s your only option Smile.

15. Have a look into the site using the browser. – We will test our “Edit” form. Remember that we did not specify special “New” form or “Display” form. This you could do the same way as you created the “Edit” form.

We see our lists in the Quick Launch.

image

Open the “Workflow 1 Tasks” list. On the Ribbon open the “Items” tab. We see our Content Type in the New Item submenu:

image

Create an item of this type. You see a standard “New” form and on it you see our three “Test” fields:

image

Enter some data and press  “Save”.

image

Open the item  in “Edit” form. Now you should see our custom list form.

image

If you click “Save As Draft” your changes will be stored in the task item. If you click “Complete Task” two item fields will be changed in addition to the changes made in the form: It sets “Status” to “Tasks_Completed” and “% Complete” to “100”. You can see this in the Code Behind file of the list form.

Test all buttons.

After “Complete Task”:

image

You see: “% Complete” is set to “100 %”.

So far our projects works as expected.

See Part 2 for the next steps… There I will show you how to create a simple Sequential Workflow that uses our Task Form.

Here is part 2: https://blog.kenaro.com/2011/03/30/walkthrough-creating-a-simple-sequential-workflow-with-a-custom-task-form-in-sharepoint-2010-using-visual-studio-2010-part-2-of-2/

Walkthrough: Creating a simple Sequential Workflow with a custom Task Form in SharePoint 2010 using Visual Studio 2010 (Part 2 of 2)

In this walkthrough I want to show you how to create a Sequential Workflow with Visual Studio 2010 for use in SharePoint 2010. – I will show how to create a custom Task Form for interaction with users. The Task form will be a native SharePoint list form. No InfoPath. There are many InfoPath samples out there but they cannot be used on a SharePoint Foundation 2010 platform. But workflows can be used on SharePoint Foundation 2010 too!

To reproduce the following steps you need to create a SharePoint site. – In the walkthrough I’ll use a Site Collection located at “http://sharepoint.local/sites/workflow”.

This blog post is part 2 of 2. It describes the steps 16 to 27. Read part 1 here: https://blog.kenaro.com/2011/03/30/walkthrough-creating-a-simple-sequential-workflow-with-a-custom-task-form-in-sharepoint-2010-using-visual-studio-2010-part-1-of-2/

You can download – and help to develop – the whole demo project source code at Codeplex: http://spworkflowdemo.codeplex.com/

(If you need assistance for the deployment process because of deployment errors please see this third post of this series: https://blog.kenaro.com/2011/04/22/walkthrough-creating-a-simple-sequential-workflow-with-a-custom-task-form-in-sharepoint-2010-using-visual-studio-2010-part-3-of-21/)

Let’s start (again)…

16. Now we need to add a list that we use to connect a workflow with. We create a “List Definition” project item named “Workflow 1 Host List”.

image

image

We change the “Elements.xml” file of the List Instance project item.

image

We change the Title, URL and Description.

image

17. Deploy the project.

18. Now we start creating a Sequential Workflow.

Create a “Sequential Workflow” project item named “Workflow 1”.

image

Create the workflow as “List Workflow”.

image

You will see all the lists we created in the previous steps. Remember: You have to (successfully) deploy the project before you can use the lists that will be created during deployment. – Without previous deployment the wizard may fail before you see the following dialog page.

In the first dropdown list choose “Workflow 1 Host List”. All other lists should be selected automatically because there is only one usable list of every needed type.

image

Select all “Workflow start” options: “Manually”, “Item Created”, “Item Updated”.

image

You get:

image

19. We will add a “Create Task With Content Type” workflow activity that will use our “Workflow 1 Task 1” we created in the steps 1 to 15 (blog post “part 1”).

Open the “Toolbox” pane and drag “CreateTaskWithContentType” into the Workflow Designer.

image

After you did this you get:

image

Now we need to configure the workflow activity in the “Properties” pane.

Set “correlationToken” to “task1” and the sub element of “correlationToken” named “OwnerActivityName” to “Workflow_1”.

image

Now we need to create code behind properties for some activity properties. As example I’ll show how to create a code behind property for “ContentTypeId”.

Click on the Button “…” at the activity property edit box:

image

In the dialog select the tab “Bind to a new member”. Enter the name “New member name” and select the “Create Property” radio button. Press “OK”.

image

Here are the property bindings you need to create:

  • “ContentTypeId” = “task1ContentTypeId”
  • “TaskId” = “task1Guid”
  • “TaskProperties” = “task1Properties”

In “MethodInvoking” type “createTask1Invoke” and press ENTER. – You’ll be directed to the code editor.

(The activity properties look like this after you finished: image)

In the method we initialize the task1-Properties we created before. The “ContentTypeId” is taken from the “Schema.xml” file of our “Workflow 1 Tasks” list where we created the Content Type “Workflow 1 Task 1”.

After that your method looks like this:

image

20. Back in the workflow designer. We drag a “While” activity from the Toolbox pane into the workflow behind the “Create Task” activity.

image

Into the “While” activity we drag a “Sequence” property from the Toolbox pane. We get:

image

Into the “Sequence” activity we drag a “OnTaskChanged” activity from the Toolbox pane. We get:

image

Now we edit the properties of the created “OnTaskChanged” activity. We have to set the “CorrelationToken” as described above. Additionally we specify new property bindings:

  • “AfterProperties” = “task1Changed1_AfterProperties”
  • “BeforeProperties” = “task1Changed1_BeforeProperties”
  • “TaskId” => Bind to the existing member “task1Guid”!!!
    image

In the “Invoked” property add the method name “task1Changed1Invoke”. – The code editor will be opened.

(The activity properties look like this after you finished: image)

21. In the code we add a property at class level:

image

This property we set inside the “OnWorkflowItemChanged” activity. It will contain the information whether the Workflow Task Item we created before was “Completed” by the assigned user.

In the “task1Changed1Invoke” method we set the “isFinished” property.

image

22. Now we need to specify the condition for the “While” activity. In the workflow designer select this activity. In the “Condition” property select “Code Condition” and expand the property. Enter “while1Invoke” in the subproperty with (the same) name “Condition”.

image

In the code editor enter the code for “while1Invoke” like this:

image

The “e.Result” property has to be “TRUE” as long as the while loop should run. It should not run anymore (“e.Result = false”) if “isFinished” is TRUE.

23. In the workflow designer add a “CompleteTask” activity behind the “While” activity. Drag the “CompleteTask” activity from the Toolbar pane into the workflow designer. We get:

image

Select the “completeTask1” activity and edit it’s properties in the Property pane.

  • Bind “TaskId” to the existing member “task1Guid”
  • Create a new member namend “task1Outcome” for binding to “TaskOutcome”
  • Set the “CorrelationToken” to “task1”

24. Whew! Smile

25. Deploy the project. – It deployed successfully ?! – Congratulations!

26. Open the browser and navigate to “http://sharepoint.local/sites/workflow”. Open the “Workflow 1 Host List”. Add a new item… – The “Workflow 1” should start automatically.

image

image

(After F5 / page refresh:)

image

Click “In Process”. We see the Workflow Status page:

image

In the “Tasks” section open the context menu of the element “(no title)”. – We did not set a title for the created “Task 1”. This could be done in the method “createTask1Invoke”.

image

Click “Edit Item”.

There it is!!! :

image

Just edit a property and click “Save As Draft”.

On the Workflow Status page you see that the workflow is still running but was modified (“Last run”).

image

Then edit the task again. Click “Complete Task”.

After that the workflow is “Completed”:

image

27. We have done it! – Now we could add a “Task 2” for this “Workflow 1” where some other data is requested from users.

With that method you will be able to add custom forms for Workflow Tasks. You could also use forms you create with Silverlight !!!

Thank you for your kind attention!

Error while creating a Enterprise Wiki sub site in SharePoint 2010

A customer of mine had a problem in a it’s SharePoint 2010 farm. An error occurred while creating a sub site of type Enterprise Wiki. The user that tried to create the sub site was not a site collection administrator and did not have Full Control permissions.

Steps:

1. Try to create the sub site:

image

2. Press “Create” button:

image

Error: “An error has occurred while processing your request.”

3. Retry with the same name for the sub site:

image

Error: “The Web site address … is already in use.”

At the same moment a site collection administrator could successfully create a Enterprise Wiki sub site!

I could solve the problem and reproduce it in my testing environment: The security settings of the site collections masterpage catalog had broken inheritance and nobody had any rights on this list. This does not seems to be a problem in most cases but it’s a problem while creating a Enterprise Wiki sub site. – Adding “read” access for “All authenticated users” solved the problem.

Kerberos error in event log on every SharePoint 2010 farm server.

I had an error in the event log on every SharePoint 2010 farm server:

image

A Kerberos Error Message was received:
 on logon session 
 Client Time: 
 Server Time: 13:1:13.0000 3/17/2011 Z
 Error Code: 0x7  KDC_ERR_S_PRINCIPAL_UNKNOWN
 Extended Error: 0xc0000035 KLIN(0)
 Client Realm: 
 Client Name: 
 Server Realm: xxxxx.NET
 Server Name: HTTP/xxxxx.net
 Target Name: HTTP/xxxxx.net@xxxxx.NET
 Error Text: 
 File: 9
 Line: efb
 Error Data is in record data.

This happens after migration of the old MOSS 2007 farm to SharePoint 2010. – On the new farm I used new accounts for the application pools.

I created SPNs on the new Application Pool accounts for the web applications.

BUT I forgot to remove the same SPNs from the old Application Pool accounts!!! – This was the (big) mistake.

ADSIEdit let me create the same SPN on different accounts. Sad smile

After removing the SPNs from the old Application Pool accounts everything works fine!

use SETSPN-Tool to find the accounts:

setspn Q HTTP/xxxx.net

You’ll get a list of all accounts that have the specified SPN “HTTP/xxxxx.net”

Additional Ribbon Sample: Custom Ribbon Tab generated by a delegate control that lists all associated list workflows and allow to start a workflow on a selected list item. (Part 3)

In the last weeks I’ve extended the sample project that I’ve created for “Ribbon Customization”. You find the project source code on Codeplex:

The related articles on my blog are:


I’ve created a new feature for my sample project: With a delegate control a Ribbon tab will be created dynamically on list view pages if there are workflows associated with the list. For every associated workflow a button will be created. -  But only for workflows that can be started manually.

To use the demo follow these steps:

1. Create a sharepoint site http://sharepoint.local/sites/ribbon.

2. Download the project from codeplex and deploy it.

3. Create one ore more workflows on the Shared Documents library at http://sharepoint.local/sites/ribbon using SharePoint Designer 2010. (I just added two list workflows on Shared Documents and added a simple “Add Comment” step to both of them.)

4. Open the document library. Upload at least one document. You get:

image

You see the “Workflows” tab Smile ??

image

OPEN IT!!

The dynamically generated workflow buttons are disabled!

image

NOW SELECT THE DOCUMENT!!

Now the workflow buttons are enabled!

image

CLICK ONE WORKFLOW BUTTON!!

You get a result window:

image

(It can contain an error message if one occurred.)

 

THAT’S ALL.

Next steps:

  • An error occures if the workflow is already associated with the item. It would be possible to create a server request while “enable check” to check on the server whether the workflow is already associated to the item.
  • Tests. Tests. Tests. => It’s not in a stable state!!

Walkthrough: Create a simple BCS connection with SharePoint Designer 2010

First: You need a SharePoint 2010 platform. You can use Foundation because BCS = Business Connectivity Services – former BDC = Business Data Catalog in SharePoint 2007 – included in this “free” edition.

Second: You need a database for the walkthrough. You can use Microsoft’s sample database “AdventureWorks”. You can download them here: http://msftdbprodsamples.codeplex.com – I’ll use the database “AdventureWorksLT2008R2”: This is the lite version of the sample database.

Third: The BCS Application of SharePoint 2010 must be configured. – Create this application in the Central Administration –> Manage Service Applications

Fourth: You need a Site Collection. – In my sample it’s “http://sharepoint.local”

1. Open SharePoint Designer 2010 (“SPD”)

Open the site collection.

image

2. Click “External Content Types” in the Site Objects Navigation.

image

3. Click “External Content Type” in the Group “New” on the Ribbon.

In the “External Content Type Information” group click the text message “New external content type” beside the label “Name”. 

image

Enter “AdventureWorks SalesOrderDetails”.

After that the same text will appear beside “Display Name”.

4. Click on the text message beside “External System”:

image

5. Click “Add Connection”

image

Select “SQL Server” in the drop down “Data Source Type” in the dialog.

image

On the next dialog enter the Database Server Name, Database Name and the Name of the new connection. Select “Connect with User’s Identity”.

image

6. Now the Data Source Explorer view is filled:

image

Scroll down and select the table “SalesOrderDetails” in the tree view.

Right click on “SalesOrderDetails”. Click on “Create All Operations”.

image

7. You get this dialog.

image

Click “Next”.

image

Click “Finish”.

8. Click “Save” or Ctrl+S.

9. After the upload click on “Create Lists & Form”.

image

Now the list will be created:

image

10. Open the browser and navigate to the site collection. You’ll see the previously created list:

image

11. Open the list view.

12. You may get the error “Access denied by Business Data Connectivity”.

image

13. Then open “Central Administration” –> Manage Service Application –> Business Connectivity Service Application

Select the BCS application. Open the context menu. Click “Set Permissions”.

image

On the next dialog add all users that should have access to the BCS app and it’s lists.

image

Click “OK”.

14. Try to open the list on the site collection.

15. You may get the error message “Login failed for user NT AUTHORITYIUSR”.

This means: IUSR account has no rights to access the AdventureWorks database.

Open SQL Server Management Studio. Open “Security” –> “Logins” (at server level).

Add “NT AUTHORITYIUSR” as new login.

image

On the “User Mapping” tab change the security settings:

image

Click “OK”.

 

16. Open the list again.

image

Now it works (for me).

Walkthrough: How to move or copy a SharePoint Designer 2010 List Workflow to another list on the same site or another site.

I had to develop a Holiday Approval Workflow with SharePoint Designer 2010. – I used a “List Workflow”. – Bad mistake! – It’s not possible to copy this kind of workflow to another list on the same site or another site.

I thought I could use the “Export to Visio” functionality with the workflow at my development site and the “Import from Visio” functionality at the destination list. – That’s impossible. You get this message:

image

(“This workflow cannot be imported because it was created in SharePoint Designer for a different site, or the original workflow has been moved or deleted. To move a workflow between sites, use Save as Template (.wsp file) instead of a Visio workflow drawing.”)

You cannot “Save as Template” because it’s a “List Workflow”.

Okay. – I’ve found a workaround.

Let’s do it in detail.

1. Create a site collection “http://sharepoint.local/sites/dev”.

2. Open SharePoint Designer 2010. Open the previously created site.

3. Open the “Workflows” view.

4. On the Ribbon click “List Workflow” and select “Shared Documents”. – We will create a workflow for the list “Shared Documents”.

image

Name the workflow “Workflow 1”. Leave “Description” empty.

image

5. Insert any workflow steps you like.

image

6. Change the workflow settings. Select “Task List” and “History List”.

image

7. Click “Publish” to publish the workflow Winking smile

8. Click “Export to Visio”. Save to Workflow as .vwi file, e.g. on the desktop.

image

9. Let’s test the workflow. – I’ve created a text file “test.txt” on the desktop. Now I upload the file to the “Shared Documents” library of “http://sharepoint.local/sites/dev”.

image

Open the item context menu. Click “Workflow”.

image

Manually start the “Workflow 1”.

*image

Click “Start”.

image

In the list view you see the workflow status.

image

Click on the status. In my case it’s “Completed”.

image

The workflow history says “Workflow executed” as specified in the workflow definition above.

10. Okay. Let’s copy the workflow to the production site “http://sharepoint.local”. – A simple “import” is impossible, because it’s a list workflow… Follow my steps.

11. Start the SharePoint Designer 2010 and open the site “http://sharepoint.local”.

12. On the Ribbon click “List Workflow” and select “Shared Documents”. – We will create a workflow for the list “Shared Documents”.

image

Name the workflow “Workflow 1 Production”. Leave “Description” empty.

image

11. Do not add any workflow step!

12. Click on “Workflow Settings” menu item on the Ribbon.

13. Click “Publish” to publish the (empty) workflow.

14. After publishing click “Export to Visio” and save the file as “workflow 1 production.vwi” on the desktop.

15. Open a Windows Explorer. Select “Desktop”. You see both “.vwi” files.

16. Add the extension “.zip” to both files.

image

 

17. Open both “.vwi.zip” files. You see:

image

18. Copy “workflow.xoml.wfconfig” from “workflow 1 production.vwi.zip” to “workflow 1.vwi.zip”.

image

19. Now remove the “.zip” extension from both files. You’ll get two “.vwi” files.

image

20. In SharePoint Designer 2010 open the site “http://sharepoint.local”.

21. Click “Import from Visio” and select “workflow 1.vwi”

image

image

Click “Next”. (Maybe you get a message: “You must close all views of this workflow before importing this file.” Then stop the import. Close all views of the Workflow and restart from Step 21.)

22. Now you see the this window:

image

That it!

23. Now the workflow designer opens:

image

24. Now you can publish the workflow and test it…

25. Be as happy as me with that !!!

PS: Of course you can use any library as destination. In the sample above it does not have to be “Shared Documents” on “http://sharepoint.local” It could be another list or library as well!

Enumerate, add, update and remove SQL Server aliases by using PowerShell

I’ve created a PowerShell script for adding, updating, enumerating und removing SQL Server aliases. – You can use the script to create/remove/enumerate both 32bit und 64bit aliases in one step or only 32bit or only 64bit aliases.

You can change this script into a PowerShell module. Just see the comment below inside the script.

I’ve tested the script on Windows Server 2008 R2 with SQL Server 2008 R2 on it. – Please post your comments how it works on other systems.

Here is the script:

#region Author: Ingo Karstein / Blog: blog.kenaro.com

SharePoint Warm Up with PowerShell

Every SharePoint farm needs a warm up Smile – After giving the IIS 7.5 Application Warmup a chance… I had to do it in another way…

I created a warmup script in PowerShell.

Here it is…

[Update 2011/08/03] New script with “timeout” capability: https://blog.kenaro.com/2011/08/03/sharepoint-warm-up-now-with-timeout/

 

$urls= @("http://sharepoint.local", "http://anothersharepoint.local")

New-EventLog -LogName "Application" -Source "SharePoint Warmup Script" -ErrorAction SilentlyContinue | Out-Null

$urls | % {
    $url = $_
    try {
        $wc = New-Object System.Net.WebClient
        $wc.Credentials = [System.Net.CredentialCache]::DefaultCredentials
        $ret = $wc.DownloadString($url)
        if( $ret.Length -gt 0 ) {
            $s = "Last run successful for url ""$($url)"": $([DateTime]::Now.ToString('yyyy.dd.MM HH:mm:ss'))" 
            $filename=((Split-Path ($MyInvocation.MyCommand.Path))+"lastrunlog.txt")
            if( Test-Path $filename -PathType Leaf ) {
                $c = Get-Content $filename
                $cl = $c -split '`n'
                $s = ((@($s) + $cl) | select -First 200)
            }
            Out-File -InputObject ($s -join "`r`n") -FilePath $filename
        }
    } catch {
          Write-EventLog -Source "SharePoint Warmup Script"  -Category 0 -ComputerName "." -EntryType Error -LogName "Application" `
            -Message "SharePoint Warmup failed for url ""$($url)""." -EventId 1001

        $s = "Last run failed for url ""$($url)"": $([DateTime]::Now.ToString('yyyy.dd.MM HH:mm:ss')) : $($_.Exception.Message)" 
        $filename=((Split-Path ($MyInvocation.MyCommand.Path))+"lastrunlog.txt")
        if( Test-Path $filename -PathType Leaf ) {
          $c = Get-Content $filename
          $cl = $c -split '`n'
          $s = ((@($s) + $cl) | select -First 200)
        }
        Out-File -InputObject ($s -join "`r`n") -FilePath $filename
    }
}

It will write a log file to the same directory as the script itself is stored.

Exceptions will be written to the event log!

Run it as “Scheduled Task” with the farm account credentials. – Check “Run with Highest Priviledges” !!!

Be sure this account can write to the scripts directory (for logging purpose)!

You can use this XML file for quick importing the scheduled task defintion. Therefore the script must be placed in the folder “C:Program FilesSharePoint Warmup”. The script itself must be named “sharepointwarmup.ps1”.

 <?xml version="1.0" encoding="utf-16"?>
 <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
   <RegistrationInfo>
     <Date>2011-01-26T00:00:37.2455395</Date>
     <Author>DOMAIN\ikarstein</Author>
   </RegistrationInfo>
   <Triggers>
     <CalendarTrigger>
       <Repetition>
         <Interval>PT5M</Interval>
         <Duration>P1D</Duration>
         <StopAtDurationEnd>false</StopAtDurationEnd>
       </Repetition>
       <StartBoundary>2011-01-26T00:00:37.2455395</StartBoundary>
       <Enabled>true</Enabled>
       <ScheduleByDay>
         <DaysInterval>1</DaysInterval>
       </ScheduleByDay>
     </CalendarTrigger>
   </Triggers>
   <Principals>
     <Principal id="Author">
       <UserId>DOMAIN\spfarm</UserId>
       <LogonType>Password</LogonType>
       <RunLevel>HighestAvailable</RunLevel>
     </Principal>
   </Principals>
   <Settings>
     <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
     <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
     <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
     <AllowHardTerminate>true</AllowHardTerminate>
     <StartWhenAvailable>false</StartWhenAvailable>
     <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
     <IdleSettings>
       <StopOnIdleEnd>true</StopOnIdleEnd>
       <RestartOnIdle>false</RestartOnIdle>
     </IdleSettings>
     <AllowStartOnDemand>true</AllowStartOnDemand>
     <Enabled>true</Enabled>
     <Hidden>false</Hidden>
     <RunOnlyIfIdle>false</RunOnlyIfIdle>
     <WakeToRun>false</WakeToRun>
     <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
     <Priority>7</Priority>
   </Settings>
   <Actions Context="Author">
     <Exec>
       <Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
       <Arguments>-command ".\SharePointWarmup.ps1"</Arguments>
       <WorkingDirectory>C:\Program Files\SharePoint Warmup</WorkingDirectory>
     </Exec>
   </Actions>
 </Task>
 

1. Copy this XML code to a file, then open the “Scheduled Tasks” management console of Windows.

2. Open the “Task Scheduler Library”, right-click on it’s node. Choose “Import”.

3. Then select the XML file.

4. In the task edit dialog: Change the execution account.

5. Save the task.

6. Now enter the password of the execution account in the credential dialog.

7. Now right-click on the created scheduled task.

8. Choose “Run” to test the task.

9. Have a look into the scripts folder in file system. there must be a file named “lastrunlog.txt” – This file will contain at most 200 lines of loggin informations!