How I upgrade long running custom Visual Studio SharePoint workflows that use InfoPath forms and that are already in production. This includes:
1. Initiation form and code changes (this is the form used to start the workflow).
2. Task Edit forms and code changes (yes, task forms can also have code-behind).
3. Workflow design and code changes.
The goal is to allow existing workflow instances (Release 1.0) to continue to completion while allowing newly started workflow instances (Release 1.1) to use the latest forms and code.
1. Preparation
a. Backup your old workflow DLL v1.0 to a ‘Release 1.0’ folder.
b. It is always a good idea to have plenty on Release 1.0 workflow instances ‘In Progress’ for testing before proceeding further. You will not be able to create new Release 1.0 instances once you have deployed Release 1.1. (I have not tried reinstate Release 1.0 by selecting ‘Allow’ for it and selecting ‘No New Instances’ for Release 1.1).
c. Change the workflow project assembly version in VS; via Project Properties; Application; Assembly Information (it changes the file 'assemblyinfo.cs') from 1.0.0.0 to 1.1.0.0. From this point the 1.0.0.0 version is immutable.
d. Change the workflow.xml file
Name="CBAWRT - Burn Permit Workflow V1.1"
Title="CBAWRT - Burn Permit Workflow V1.1"
Description="CBAWRT - Burn Permit Workflow V1.1"
CodeBesideAssembly="mcsfbi.workflow.BurnPermit, Version=1.1.0.0, Culture=neutral, PublicKeyToken=d2e05a78a46f43a8"
e. Keep the same wsp solution id.
f. Keep the same feature guid.
g. Keep the 1.0.0.0 version of the workflow DLL in the GAC; a new 1.1.0.0 version will be created and added to the GAC.
h. Keep the original Release 1.0 document library workflow association intact.
i. Always test the full process in a non-production environment first.
2. Initiation form changes
You may change the existing Initiation form with some restrictions outlined below. Initiation form (templates) are published in InfoPath to the Forms Server and uploaded via Central Admin. Their version number is auto incremented when published; code-behind is serialized as a part of the form template. Use ‘upgrade the form template if it already exists’.
Once the changed Initiation form is Published and Uploaded, both new and existing forms will use the new form template (layout), xsn (xml schema) and form code. Already existing Initiation forms will continue to use the version of the workflow (dll) to which they were associated. New Initiation forms will use the version of the workflow (Release 1.1) to which they are associated (see below).
Once the changed Initiation form is Published and Uploaded, both new and existing forms will use the new form template (layout), xsn (xml schema) and form code. Already existing Initiation forms will continue to use the version of the workflow (dll) to which they were associated. New Initiation forms will use the version of the workflow (Release 1.1) to which they are associated (see below).
a. Schema changes (xsd) - changing the form's Main DataSource
1. Field additions are allowed. Field deletions or field definition changes (e.g. from string to Boolean) to existing schema fields are not allowed.
2. Newly required fields should be enforced via InfoPath rules not via schema enforcement because older Initiation forms will fail to validate against the new xsd.
3. Avoid changing any of the field names in the Data Source section. Pay close attention to messages like the one below. The correct answer is ‘No’.
4. If you have a new data source field used in code see 'Footnote 1'.
4. If you have a new data source field used in code see 'Footnote 1'.
b. Promoted Field changes
Each Initiation form template has a site Content Type associated with the form. You may add fields via InfoPath - Tools; Form Options; Property Promotion to allow those fields to be available in the document library (list) which holds your Initiation forms.
After publishing the Initiation form, and de-activating and re-activating the form’s site collection feature, you will see the Property Promotion fields added to the Initiation form’s Content Type (in Site Settings; Site Content Types). Normally you can then add the Content Type to the document library to allow your Initiation form to open when the user clicks ‘New’ in the document library. Changing the Content Type in the document library requires that nothing is using it. If you need to add new property promotion fields for your new release (Release 1.1) and are live in production (Release 1.0), you will get the ‘Content Type is still in use’ message. One way to overcome this is to delete any form instances that use the Content Type. This is probably not viable in Production.
At this point I chose to create a second copy of my Initiation form, which will create a new Content Type, ‘Chemical Approval Form V1.1’ in my case; which I can add to the document library. Ensure the new Content Type is the default and that the old version is not available for selection when 'New' is clicked. Below (right) you see the columns in my document library are from the original 'Chemical Approval Form content type as well as the new ‘Chemical Approval Form V1.1’ content type.
|
|
3. Task Edit form changes
I upgrade all existing Task Edit form instances to use the latest version of the task form and code. You also have the option of using a completely new task edit form with a new URN and new form name (set in the workflow.xml file); but here we assume that we are changing existing task edit forms.
a. Schema changes
i. Field additions are allowed. Field deletions or field definition changes (e.g. from string to Boolean) to existing schema fields are not allowed.
ii. Newly required fields should be enforced via InfoPath rules not via schema enforcement because older Initiation forms will fail to validate against the new xsd.
iii. Avoid changing any of the field names in the Data Source section. Pay close attention to messages like the one below. The correct answer is ‘No’.
iv. If you have a new data source field used in code see 'Footnote 1'.
b. Make any Task Edit form changes including layout, field additions, rule changes, code changes.
c. Publish the forms as you did previously in Release 1.0. The old forms will automatically be upgraded.
d. Task Edit code-behind generates a DLL which should be extracted by using ‘Save as Source Files’ and copied to the same location as the form’s published xsn file.
e. Both the published task edit form xsn file and the corresponding DLL will need to be copied to the TEMPLATE/FEATURES directory in the SharePoint hive and will replace the Release 1.0 versions (since we are upgrading all task edit forms). Before replacing the task form DLL files, you will need to recycle the application pool. This avoids an ‘access denied’ message .
f. I am unsure whether existing task edit forms (created when only workflow version 1.0 was available) will continue to use the workflow 1.0 dll once workflow 1.1 dll becomes available, or whether they will use the latest workflow dll. This could become important if there is new code in the workflow task’s OnTaskChanged event. It may expect a new AfterProperty which might be empty in older task edit forms.
4. Workflow changes
a. Any changes to the workflow code interface (such as: property changes, activity adds/removes, etc.) require a new version of the workflow DLL. This represents the vast majorityof workflow changes. Without a new DLL version, you will get ‘This task is currently locked by a running workflow and cannot be edited.’ on any old 'In Progress' workflows.
A new version of the workflow DLL will be placed into the GAC and will co-exist with the 1.0.0.0 version. For example:
You may change the workflow in any way you like, because you will have a new version of it, leaving the old version of the workflow DLL untouched. You should edit the original workflow designer and source code as there is no need to maintain two separate versions of source.
A new version of the workflow DLL will be placed into the GAC and will co-exist with the 1.0.0.0 version. For example:
You may change the workflow in any way you like, because you will have a new version of it, leaving the old version of the workflow DLL untouched. You should edit the original workflow designer and source code as there is no need to maintain two separate versions of source.
b. Alternatively, where the code interface has not changed – you may
i.EITHER: upgrade and replace the workflow DLL 1.0.0.0 version keeping the version number the same (this is fine for spelling changes for example).
ii.OR use a new version 1.1.0.0 and set the binding redirect as shown.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WorkflowLibrary1" publicKeyToken="8afb6d596a769080" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="1.1.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
c. Build and redeploy the workflow
You may perform these steps manually if you don’t want to use or don’t trust solution deployment.
You may perform these steps manually if you don’t want to use or don’t trust solution deployment.
i.Recycle the app pool (or use IISReset) – to avoid ‘Acces Denied’ or ‘Sharing Violation’ messages against the task edit form dlls.
ii.Retract and Delete the old solution using stsadm or Powershell
– this will remove the 1.0.0.0 version of the workflow DLL from the GAC and the 1.0.0.0 versions of the task edit form xsn and dll files from the SharePoint hive
– this will remove the 1.0.0.0 version of the workflow DLL from the GAC and the 1.0.0.0 versions of the task edit form xsn and dll files from the SharePoint hive
iii.Add and Deploy the solution
- this will add the 1.1.0.0 version of the workflow DLL to the GAC and add the task edit form xsn and dll files to the SharePoint hive.
- this will add the 1.1.0.0 version of the workflow DLL to the GAC and add the task edit form xsn and dll files to the SharePoint hive.
iv.Re-add 1.0.0.0 version of the workflow DLL to the GAC.
v.Deactivated and Uninstall Workflow Feature
vi.Install and Activate Workflow Feature – this will set the 1.0 association to ‘No New Instances’
vi.Install and Activate Workflow Feature – this will set the 1.0 association to ‘No New Instances’
vii.Ensure 1.0.0.0 version and 1.1.0.0 version of the workflow DLL are both in the GAC
d. Go to the forms library; form library settings; workflow settings; and associate the new version of the workflow to the Initiation form content type (here ‘Burn Permit Request Forms’). Include the version in the ‘Name’ field.
e. Note: normally, deactivatefeature,uninstallfeature,installfeature,activatefeature using the same WF version would break the WF association between the document library and the already running workflow template and their ‘In Progress’ tasks would not run. BUT, if you deployed a new version (1.1.0.0) of the workflow template and DLL (set in workflow.xml), this will not invalidate existing in-progress workflows. Reinstalling and reactivating the feature will set the existing association to ‘No New Instances’ because we are using the same solution id and the same feature guid in the feature.xml file as release 1.0.0.0 when deploying the solution.
Footnote 1:
Extra code may be needed to bring old forms up to spec. For example, if the ‘CurrentUser’ field is added in Release 1.1 and referenced in form code, we must allow for the field to not exist in older (Release 1.0) forms, by testing for null. Alternatively the new field can be added programmatically to older (Release 1.0) forms as shown in method
AddCurrentUserIfMissing() below. This method executes from the FormEvents_Loading event to ensure backwards compatibility.
AddCurrentUserIfMissing() below. This method executes from the FormEvents_Loading event to ensure backwards compatibility.
private void AddCurrentUserIfMissing()
{
if (CurrentUser == null)
{
XPathNavigator navRoot = CreateNavigator();
navRoot = navRoot.SelectSingleNode("/my:ReviewForm", NamespaceManager);
navRoot.AppendChildElement(navRoot.Prefix, "CurrentUser",
navRoot.LookupNamespace(navRoot.Prefix), "");
navRoot.LookupNamespace(navRoot.Prefix), "");
}
}
private string CurrentUser
{
get
{
XPathNavigator navNode = CreateNavigator().SelectSingleNode
("/my:ReviewForm/my:CurrentUser", NamespaceManager);
("/my:ReviewForm/my:CurrentUser", NamespaceManager);
if (navNode == null)
return null;
else
return navNode.Value;
}
set
{
XPathNavigator navNode = CreateNavigator().SelectSingleNode
("/my:ReviewForm/my:CurrentUser", NamespaceManager);
("/my:ReviewForm/my:CurrentUser", NamespaceManager);
nav navNode.SetValue(value.ToLower());
}
}
REFERENCES:












