DynamicUpdate in .Net 4.5
-
Friday, April 20, 2012 7:22 AM
I am trying to understand and also test dynamic update consept in WF 4.5.
so, i am loading original (source) and modified(target) workflows for create update map.
WorkflowService sourceWorkflow = (WorkflowService)XamlServices.Load(ActivityXamlServices.CreateReader( new XamlXmlReader(@"d:\old\Retail\LoanDomain\Application\Web\loan.xamlx", new XamlXmlReaderSettings { LocalAssembly = Assembly.GetExecutingAssembly() } ))); WorkflowService targetWorkflow = (WorkflowService)XamlServices.Load(ActivityXamlServices.CreateReader( new XamlXmlReader(@"d:\new\Retail\LoanDomain\Application\Web\loan.xamlx", new XamlXmlReaderSettings { LocalAssembly = Assembly.GetExecutingAssembly() } ))); DynamicUpdateServices.PrepareForUpdate(sourceWorkflow.Body); DynamicUpdateMap updateMap = DynamicUpdateServices.CreateUpdateMap(targetWorkflow.Body);
But at last line, while calling CreateUpdateMap, I get below funny exception;
The workflow definition does not have an attached copy of its original definition. Before making updates to the workflow, call DynamicUpdateServices.PrepareForUpdate to save a copy of the original definition.
Clearance Edit:
When I changed the below line
DynamicUpdateMap updateMap = DynamicUpdateServices.CreateUpdateMap(targetWorkflow.Body);
to
DynamicUpdateMap updateMap = DynamicUpdateServices.CreateUpdateMap(sourceWorkflow.Body);
works fine. Which means there is no problem while loading source or target workflow.
- Edited by Ugur KARATAS Friday, April 20, 2012 10:22 AM
- Edited by Ugur KARATAS Friday, April 20, 2012 10:22 AM
- Edited by Ugur KARATAS Friday, April 20, 2012 10:26 AM
- Edited by Ugur KARATAS Friday, April 20, 2012 10:26 AM
- Edited by Ugur KARATAS Friday, April 20, 2012 11:41 AM
- Edited by Ugur KARATAS Friday, April 20, 2012 11:41 AM
- Edited by Ugur KARATAS Friday, April 20, 2012 12:06 PM
All Replies
-
Friday, April 20, 2012 5:03 PM
In order to become familiar with DynamicUpdate in WF 4.5, I would suggest that you take a look at the following two samples:
-
Saturday, April 21, 2012 3:26 PMThanks for reply.
I already checked and tested those samples. Also i used them for creating my application.
I think when i call
DynamicUpdateServices.PrepareForUpdate(sourceWorkflow.Body);
DynamicUpdateServices is hashing source workflow with its hash code. Then calling CreateUpdateMap with target workflow body, DynamicUpdateServices is not found in reporsitory with its HasCode.
Because when i try to call PrepareForUpdate(sourceWorkflow.Body) first, than Change sourceWorkflow.Body directly, and at last calling CreateUpdateMap, i can get updateMap as expected.
But scenario requirement is creating update map between original and changed workflows those are published.- Edited by Ugur KARATAS Friday, April 27, 2012 6:53 AM
-
Tuesday, April 24, 2012 8:10 AMStill no progress...
-
Friday, April 27, 2012 6:58 AM
Is there any possibility to creating update map from workflow definition without loading workflow with XamlServices.Load ?
The real question is : How we can create update map between "published" and "will be published" versions of workflow.
- Edited by Ugur KARATAS Friday, April 27, 2012 7:01 AM
- Edited by Ugur KARATAS Friday, April 27, 2012 7:02 AM
-
Monday, April 30, 2012 5:46 PM
Ugur,
As you have noticed, it is not possible to dynamically update a Workflow (in your case "sourceWorkflow") to a completely different and arbitrary Workflow (in your case "targetWorkflow"). This behavior is "By Design". You would need to modify the original Workflow; this way the Workflow engine will have the required means to calculate the UpdateMap.
Thank you,
Hani
-
Friday, May 04, 2012 12:43 PMThanks Hani,
I see "By Design".
The question is : In our environment ( A Bank ), we are creating deployment packages then continue to development. Mostly two or three developer is working same workflow (for imagination; think loan process-it has 20 state, 50 transitions. Average duration is 20 days.) daily. Dynamic Update is looking not applicable for our environment.
Our unlovely answer is adding new can create instance operation to beginning of workflow for creating new instance and setting state. And after deployment killing existing instances, and create new workflow with set state within operation.- Edited by Ugur KARATAS Friday, May 04, 2012 12:44 PM
-
Wednesday, May 16, 2012 2:10 PMModerator
Hi,
Yours is a typical dynamic update scenario. Workflow A1 is deployed and there are running instances. Then a new version is deployed, workflow A2. New instances are started with A2, but there are still some running instances of A1 that need to be updated to the functionality of A2. In order to do that, you would need to:
- Load up definition A1
- PrepareForUpdate
- Make the changes in the definition so that it matches A2
- CreateUpdateMap
- This will give you an updated definition based off of A1 that matches the functionality of A2, let's call it A1.1, and an update map.
- Iterate all the persisted instances of A1, apply the update map and repersist them. They are now A1.1, which matches the functionality of A2
At this point you have 2 workflow definitions deployed (and two workflow identities): A2 and A1.1. Both have the same functionality. You start all new instances using A2, and you finish up the A1.1 instances (which match the functionality of A2) using the new A1.1 definition.
There is no way to create an update map between A1 and A2, the only way to get from A1 to A2 is to create A2 by loading up A1, preparing for update, making the changes, and creating the update map which would return A2.
If you have not already deployed the new independently developed A2, then you can create A2 using the steps above, and then you would have only the one workflow definition to start your new instances with, and to resume existing instances.
Note that you do not need to make the changes programatically; you could load up the definition in the rehosted designer and make your changes that way.
Steve Danielson [Microsoft]
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm
- Edited by Steve DanielsonMicrosoft Employee, Moderator Wednesday, May 16, 2012 9:58 PM
- Edited by Steve DanielsonMicrosoft Employee, Moderator Wednesday, May 16, 2012 9:59 PM
-
Thursday, June 21, 2012 6:03 PM
Hi,
Yours is a typical dynamic update scenario. Workflow A1 is deployed and there are running instances. Then a new version is deployed, workflow A2. New instances are started with A2, but there are still some running instances of A1 that need to be updated to the functionality of A2. In order to do that, you would need to:
- Load up definition A1
- PrepareForUpdate
- Make the changes in the definition so that it matches A2
- CreateUpdateMap
- This will give you an updated definition based off of A1 that matches the functionality of A2, let's call it A1.1, and an update map.
- Iterate all the persisted instances of A1, apply the update map and repersist them. They are now A1.1, which matches the functionality of A2
At this point you have 2 workflow definitions deployed (and two workflow identities): A2 and A1.1. Both have the same functionality. You start all new instances using A2, and you finish up the A1.1 instances (which match the functionality of A2) using the new A1.1 definition.
There is no way to create an update map between A1 and A2, the only way to get from A1 to A2 is to create A2 by loading up A1, preparing for update, making the changes, and creating the update map which would return A2.
If you have not already deployed the new independently developed A2, then you can create A2 using the steps above, and then you would have only the one workflow definition to start your new instances with, and to resume existing instances.
Note that you do not need to make the changes programatically; you could load up the definition in the rehosted designer and make your changes that way.
Steve Danielson [Microsoft]
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm
Thanks Steve for the great answer.
So i have the same problem as the OP. My case is that I have A1 which is copied and renamed to A2 then I add one new state to the copied A2 workflow. Is there a way to dynamic update this without making the changes programatically when making the update map?Something like compare the two .xaml files to see what is different and then create an update map from the difference?
Thanks
- Edited by AntiSniperSpy Thursday, June 21, 2012 6:03 PM
-
Thursday, June 21, 2012 6:54 PMModerator
Hi,
I do not know of a way to retroactively create an update map in the manner that you describe. However, you do not have to make the changes to the v1 definition programmatically. You do have to start with the v1 definition however. The steps below (from above) are an outline of the process.
- Load up definition A1
- PrepareForUpdate
- Make the changes in the definition so that it matches A2 << This step can be done any way you want
- CreateUpdateMap
However, step 3 does not need to be done programmatically. What you could do is load up v1 of the definition, make the call to PrepareForUpdate, and then serialize out the activity builder. At this point you should be able to load it into the designer in visual studio, make the desired changes, and then save it. Then you could reload it, and create the update map (I do not have a definitive set of steps but I plan to make a blog post/video walkthrough of this process)
Thanks,
Steve Danielson [Microsoft]
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm -
Sunday, June 24, 2012 10:35 PM
Hi,
I have the same problem too. All the samples just show, how to update a "normal" workflow, but not how to update a Workflow-Service.
Can someone provide us with such a sample?
For clarification, below I place some code that bases on the mentioned samples. It hosts a Workflow-Service (see method StartService) and tries to update a service-instance (see method Update). But the Update does not work cause the method load leads to the mentioned exception (see comment within the code).
What did I do wrong?
Wishes,
Manfred
using System; using System.Activities; using System.Activities.DurableInstancing; using System.Activities.DynamicUpdate; using System.Activities.Statements; using System.Activities.XamlIntegration; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.DurableInstancing; using System.Runtime.Serialization; using System.ServiceModel.Activities; using System.Text; using System.Threading.Tasks; using System.Xaml; namespace SideBySideSelfHostSample { class Program { static void Main(string[] args) { Console.WriteLine("s: Start Service, u: Update"); var option = Console.ReadLine(); if (option == "s") { StartService(); } else { Update(); } } private static void Update() { // Load and prepare for Update string path = @"C:\Users\Manfred\Documents\Visual Studio 2012\Projects\SideBySideSample\DynamicUpdateSelfHostSample\Ansuchen_V2.xaml"; //var path = @"C:\Users\Manfred\documents\visual studio 2012\Projects\SideBySideSample\SideBySideSample\Ansuchen.xamlx"; var settings = new XamlXmlReaderSettings(); settings.LocalAssembly = Assembly.GetExecutingAssembly(); var reader = new XamlXmlReader(path, settings); var builderReader = ActivityXamlServices.CreateBuilderReader(reader); var ab = XamlServices.Load(builderReader) as ActivityBuilder; DynamicUpdateServices.PrepareForUpdate(ab); // Update var seq = ab.Implementation as Sequence; var newSendMessageAction = new SendMessage() { Message = "Test-Message", MessageId = "4711", UserName = "system" }; seq.Activities.Add(newSendMessageAction); var map = DynamicUpdateServices.CreateUpdateMap(ab); var dcs = new DataContractSerializer(typeof(DynamicUpdateMap)); using (var fs = new FileStream(@"c:\temp\map.map", FileMode.Create)) { dcs.WriteObject(fs, map); } using (var sw = File.CreateText(@"c:\temp\newWf.xaml") ) { var xamlWriter = ActivityXamlServices.CreateBuilderWriter( new XamlXmlWriter(sw, new XamlSchemaContext())); XamlServices.Save(xamlWriter, ab); } // UPDATE Console.WriteLine("WorkflowId: "); var id = Guid.Parse(Console.ReadLine()); var store = new SqlWorkflowInstanceStore(@"Data Source=(localdb)\SideBySideSample;Initial Catalog=PersistenceStore;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False"); var instance = WorkflowApplication.GetInstance(id, store); var newVersion = new WorkflowIdentity(); newVersion.Name = "SomeWorkflow"; newVersion.Version = new Version(2,1,0,0); var wfApp = new WorkflowApplication(new Ansuchen_V2(), newVersion); /* * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * Load leads to this exception: * The update map does not match the workflow definition. Please make sure that this is the correct map for this definition, and that the serialized map has not been manually altered. */ wfApp.Load(instance, map); wfApp.Persist(); wfApp.Unload(); } private static void StartService() { // -- Service V1 erzeugen -- var bodyV1 = new Ansuchen_V1(); var serviceV1 = new WorkflowService { Name = "AnsuchenWorkflow", DefinitionIdentity = new System.Activities.WorkflowIdentity { Name = "AnsuchenWorkflow", Version = new Version("1.0.0.0") }, Body = bodyV1 }; // -- Service V2 erzeugen -- var bodyV2 = new Ansuchen_V2(); var serviceV2 = new WorkflowService { Name = "AnsuchenWorkflow", DefinitionIdentity = new System.Activities.WorkflowIdentity { Name = "AnsuchenWorkflow", Version = new Version("2.0.0.0") }, Body = bodyV2 }; using (var host = new WorkflowServiceHost(serviceV2, new Uri("http://localhost:8080/AnsuchenWorkflowService"))) { host.SupportedVersions.Add(serviceV1); host.Open(); Console.WriteLine("Service gestartet ..."); Console.ReadLine(); } } } }
-
Thursday, June 28, 2012 9:12 PM
Thanks looking forward to the blog post/video.Hi,
I do not know of a way to retroactively create an update map in the manner that you describe. However, you do not have to make the changes to the v1 definition programmatically. You do have to start with the v1 definition however. The steps below (from above) are an outline of the process.
- Load up definition A1
- PrepareForUpdate
- Make the changes in the definition so that it matches A2 << This step can be done any way you want
- CreateUpdateMap
However, step 3 does not need to be done programmatically. What you could do is load up v1 of the definition, make the call to PrepareForUpdate, and then serialize out the activity builder. At this point you should be able to load it into the designer in visual studio, make the desired changes, and then save it. Then you could reload it, and create the update map (I do not have a definitive set of steps but I plan to make a blog post/video walkthrough of this process)
Thanks,
Steve Danielson [Microsoft]
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm -
Wednesday, September 12, 2012 1:40 PM
Everything we do in Visual Studio is at 'design time'... Workflow Versioning then introduces a 'run time' requirement. If you then try and use the rehosted designer it will take masses of time to try and replicate the visual studio functionality, including a 'Solution Explorer' to update your activities. You then don't get intellisense which make the whole thing slower to use!!
Most solutions will be modular.. so you probably have a parent activity, with a child activity, inside another child activity. When you come to make the update map you first have to apply it to the activity youve changed, then apply it to all its parents until your at the root level which you persist to the database.. this isnt out of the box!
How much time do you think us dev's have to monitor and update workflows!?
We've now bailed on workflow persistence and are managing state ourselves. Sadly we have an if statement in each high level activity to dictate whether to run..but it beats weeks of work implementing this lame 'run time' solution.
-
Friday, February 08, 2013 10:14 PMAny update to having a blog post/video... Thanks
-
Wednesday, February 27, 2013 9:52 PMModerator
The video is still in the works but the WF45 Getting Started Tutorial now has step by step walkthroughs of both side-by-side hosting, and dynamic update, and is available here: http://aka.ms/WF45GettingStarted
Step 7 (the final step) walks through all the steps above: Preparing the workflow definition for dynamic update, programmatically modifying the workflow definition, creating the update map, compiling the new definition into an assembly, applying the update map to persisted instances, and then resuming the updated instances.
Please take a look and see if it gives you what you need.
Thanks!
Steve Danielson [Microsoft]
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

