Freigeben über


Any Questions?

Is there anything about Windows Workflow Foundation (WF) that you would like to know and feel is an appropriate topic for this blog?  If so, please add a comment to this post.  I will use the comments as seeds for future postings.  Even if someone has already posted your specific question, please add your own comment as well so that I can do a better job prioritizing.

Note that posting here does not in any way guarantee that I will respond, but I will try to do the best that I can.  Another good resource for general WF questions is the https://www.windowsworkflow.net.  This site has articles and samples of its own as well as links to other blogs and related MSDN forums.

Comments

  • Anonymous
    March 19, 2006
    I am someone who designed my own workflow system for a previous business a few years ago, and is now hoping to use WWF rather than build my own. I'll tell you about how I am thinking of using WWF see if that helps..

    My first perception is that a lot of the examples concentrate on building a workflow process. A higher-level overview seems to be missing (or perhaps I missed it?) - what are all the 'building blocks', how do the workflow assemblies, runtime, persistence, tracking etc. all work together, and how they might interact with existing applications and databases. Obviously there may be so many possible combinations as things are so flexible, but an example of how this might work would be useful.

    For example, my app has a data-access layer with business logic, based on SQL 2005, with the front-end in ASP.NET 2.0. I have some back end processing running on the server as NT services. I assume I will need to have a service running the workflow runtime as my workflow 'engine', and persist to a database.

    My first test use of WWF in this application is to be a credit control workflow. When a customer's account is unpaid beyond the due date, it will need to initiate a credit control workflow process. As this is largely event-driven I am building it as a state machine WF.

    The first state DetermineAction is transitory: will decide if the nice reminder letter (slightly overdue) goes out, or the firm-demand letter goes out, before setting a new WaitForAWeek state.  If the debt is very large, it may decide to skip the letters and go straight to the RequiresPhoneCall state, I guess that this might be a good place to Rules but I have not got into those much yet.

    At any point in the workflow the customer might pay up, so we need to have a workflow-level activity handler (is that the right name?) that completes the WF, regardless of the current state. That seems to be possible having eventActivities at the top of the workflow, although I've not seen it written about (I discovered it by accident!).

    The WaitForAWeek state will have a design-time delay of seven days, after which it reverts to DetermineAction state again. If we have sent the first letter, we go to the second. If the second has been sent, we go to RequiresPhoneCall state. However I might need to make the delay dynamic based on the size of the debt, so larger debts are chased more quickly - have not seen how the DelayActivity could be made dynamic rather than static so far.

    The RequiresPhoneCall state is where I need figure out how 'assignment' of workflow activities works in WWF.  I have not yet figured out how to locate all workflows in a current state but I assume it can be done.

    Acutal assignement seems to be something that's up to the developer to implement, presumably either in the workflow by storing the assignment there or by storing the assignment in the app along with the instanceID. I don't know how efficient trying to query a set of workflow would be (especially if they have been persisted to db?) = what's the best way.

    When someone chases the debt they may need to see what workflow has done - is a state history something provided or something we developers need to store?

    As we expand workflow into other areas it's likely on person would need to deal with lots of different activities, so I would want to have a way of presenting all the activities to the user. This is allied to the earlier issue of where I store assignment: presumably it would be best done by me on my database. However if I do that, and some other activity has ended the workflow (e.g. customer has paid) my system will be out of date.

    Hope that's a useful example and some of the questions I am encountering as I try to figure out WWF. That said it feels to me that it could be the next killer-app for Microsoft.

  • Anonymous
    March 21, 2006
    The comment has been removed

  • Anonymous
    March 22, 2006
    Many thanks for the very comprehensive reply! - and congratulations to the WF team on a really excellent product. I think "killer app" is an appropriate epithet.

    Point 3 about "root" Event Handlers (it that the right term?) is what I guessed so it's good hear confirmation - I would suggest if someone does a statemachine sample they add one of these to illustrate its usage. For example in my app I need a "CustomerHasPaidDebt" Event Handler in all tasks to stop the process, so these are ideal.

    I did finally find a bit of an 'overview' of WF in the helpfile with Beta2 - i had only been searching online when I posted.

    Assignment: your points on assignment again are what I suspected - that the persistence store should not be treated as if it's a queriable database, e.g. find all workflow of type X in state Y and assigneduser = Z.

    I think assignment is going to be a FAQ as most workflow (certainly most statemachine workflow) will use it in some way, and it might be an idea to provide a sample approach (the helpdesk app seems like a logical one to extend so that it is possible to show, although it does not use a statemachine).

    Assigment held on the app raises the issue of concurrency since workflow might move on to a new state by the time the user tries to action the task. I think the best route is as you suggest to let workflow handle assignment (in stateInitialisation perhaps) and also deassignment (in stateFinalization), notifying the app via the interface that it needs to create or delete the task for assignment tracking purposes.

  • Anonymous
    April 20, 2006
    Hello,

    I just created my first WF workflow and I'm curious if what I did is correct. I wanted to do a latitude/longitude lookup using a web service after the user enters a location string. The user clicks the update button and I fire off my workflow which reads/writes to the user profile table. In order for this to happen in the background I added the DefaultWorkflowSchedulerService to my service in my web.config. Everything seems to be working fine during testing, but I'm wondering if this is a valid use of WF?

    Thanks!

  • Anonymous
    April 25, 2006
    The comment has been removed

  • Anonymous
    May 11, 2006
    Is there any way to use delay in an state machine workflow?

  • Anonymous
    May 19, 2006
    The comment has been removed

  • Anonymous
    June 09, 2006
    Hi,

    Can you answer some of the questions posted here:
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=452829&SiteID=1

    Thanks.

  • Anonymous
    August 09, 2006
    Hi there! Great blog you have.

    I have a strange workflow to implement with WF.

    First, there're 4 states, and 4 approvers of course for each state. The strange thing is that when the user initiates the workflow, he/she must specify the user for each of the first two states, the others are fixed.

    So it would be:

            First State       Approver defined by user (creator)
           2nd State          Approver defined by user (creator)
           3rd State           Fixed
           4th State           Fixed

    Do you have any idea of how could this apparently simple workflow could be implemented?

    thanks in advance!

    Victor

  • Anonymous
    August 15, 2006
    prideu2, I'm not sure where you are running into trouble.  First, just to clarify, is there a single approver per state making a total of 4 approvers per workflow, or are there 4 approvers per state?  One sentence of your post contradicts the table you've created.

    Second, are you wondering how the workflow creator could specify parameters (the approvers) at creation time?  Are you wondering how to have the workflow creator specify the approvers when states 1 and 2 are entered?  Are you wondering how to set data on your activities at runtime?

    Let me know and I'll try to help.

    Nate

  • Anonymous
    August 17, 2006
    I'm trying to build a workflow modification form for MOSS that allows a user to reassign workflow (InfoPath form) tasks to other users (in case another user is away, etc.). The ECM Sample Starter Kit has an example that uses an InfoPath Modification form to do just that. However, it is sequential, and I'm using a state machine workflow.

    Looking at the code for the example, I can see that it has an 'EnableWorkflowModification' step to, well, enable a modification form. I looked this up on the MSDN site, and found that the pages I saw (http://msdn2.microsoft.com/en-us/library/ms550177.aspx and (http://msdn2.microsoft.com/en-us/library/ms480794.aspx) discuss the 'scope' of the enabled form.

    However, scopes don't seem to make much sense in the context of a state machine workflow. The modification form would need to be enabled for a state, not a scope. There are no 'IEventActivity' steps to block the progress of the workflow while it is in a scope. Thus, 'rest' condition of the workflow is in a StateActivity, waiting for an event - and it is only in this condition that a user would have a chance of actually using a modification form.

    Could you clarify how I'm meant to use Modification forms in SharePoint 2007 state machine workflow? Or is this too specific to SharePoint?

  • Anonymous
    August 31, 2006
    AndyBurns, sorry that it took me so long to get back to you, but you should talk to the SharePoint people about this.  This is far too specific to their usage of our product for me to be any help.  Again, sorry for the delay.

  • Anonymous
    September 28, 2006
    Just to confirm Quango's comment, I just checked, and it does not appear to be possible to dynamically set a DelayActivity's timeout duration in state machine workflow.

  • Anonymous
    September 28, 2006
    AndyBurns,

    From my response to Quango:

    Delays can be set dynamically.  I have not done this in a state machine, but there should be two ways to get the results you want.  First, in the state initialization handler you can access the delay activity using a CodeActivity by walking the tree and set the TimeoutDuration property.  Second, you can subscribe to the InitializeTimeoutDuration event, cast the sender to DelayActivity, and set the TimeoutDuration on that object.

  • Anonymous
    September 28, 2006
    The comment has been removed

  • Anonymous
    September 28, 2006
    The comment has been removed

  • Anonymous
    September 28, 2006
    Thanks for the reminder...

    Ugh. Oh dear. If that is the only way to do it, then I quit. It's too easy to forget/miss this when writing in workflow - it's just yet another counter-intuitive approach that WF imposes. Uninstall WF and 3.0..

    As you can see from my original post in March ('Quango' at the top) I've been looking at workflow for a LONG time and overcome many of the conceptual problems.  I even managed to overcome the horrific minefield that is 'HandleExternalEventActivity' with its Heath-Robinson string of interfaces, classes and services to send a single message, by stuffing workflow inside a webservice and writing webmethod wrappers.

    But in the end I found that using WF would generate more effort and coding than it acutally provides in benefits. There are just too many problems at every turn once you try to implement it in a real-world situation and I know I'm not alone in this feeling!

    WF is too complicated. Its like being required to have a degree in mechanical engineering to be allowed to drive a car. It's not the direction .NET has been taking us since 2000 - simpler, higher-level and more powerful classes.

    What worries me is that if experience developers like myself are giving up on it in the beta phase, does this system stand any chance of making it to 2.0 ?

  • Anonymous
    January 16, 2007
    I have an activity property whose type is like a metadata hierarchy: the root is a parent whose "value" is a collection of metadata items; each item is an integer metadata, string metadata, etc. or another parent metadata. An integer metadata has a Name, Value, Default (value) properties, etc. an so on.The problem is when I want to bind say an integer property in another activity to an item inside this hierarchy. The binding editor only shows the "root" and item[0]. This metadata hierarchy is actually populated at design time, e.g. the root has a collection of 5 items, so I'd like to see item[0], item[1], etc. and bind to the Value property of 3rd item (like activity1.Metadata.Value[3].Value).The second situation is the reverse of this: I'd like to bind say activity1.Metadata.Value[3].Value in the hierarchy to an integer property of another activity. But there is only one dependency property (of type MetadataProperty) in my activity, i.e. item 3 does not have a corresponding (bindable) dependency property.Questions:can the bindable editor be replaced with a custom one? what are the formats for the Path property of the ActivityBind? seems that could be like Myproperty.SubProp1, but does it support an expression like this: Metadata.Value[3].Value? besides, the ActivityBind class is sealed: I cannot enhance it, or even change its serialization, can I? How does the property grid add the "blue dot" for property binding? is it tied in having a dependency property with the name of the property and "Property" appended to it?

  • Anonymous
    August 26, 2008
    The comment has been removed

  • Anonymous
    August 26, 2008
    mconstantin, allow me to apologize for never responding to your question.  In the interest of having a complete archive, my response would have been: I'm not that familiar with the designer or the binding mechanism (I'm more of a core runtime guy) so I'd suggest the MSDN WF forums for questions of that nature.  These forums are actively watched by members of the team and turn around time is pretty good.

  • Anonymous
    August 26, 2008
    Bill Bassler, this is an interesting (and not uncommon) scenario that you bring up.  WF in NetFx 3.0 has very limited support for what we'll call BYOT (bring your own transaction) but luckily that support intersects with what you are interested in doing.It's been a whlie since I've worked with this stuff, so some of my details might be a bit off, but it should go something like this ...The WorkflowInstance.Unload API does not suppress the ambient transaction.  This means that if you call Unload with Transaction.Current set then the SqlWorkflowPersistenceService will use that transaction to save the instance into the database.This is a rather dangerous feature, however, because it can be difficult to actually save a workflow in the desired state given that it could be running at any arbitrary point on any arbitrary thread.  Unless, of course, you are using the ManualSchedulerService.So, the proper way to set this up is to configure the WorkflowRuntime with the SqlWorkflowPersistenceService and the ManualSchedulerService.  Create as many instances as you need, call Unload under the same transaction, and then commit the transaction.One other caveat here is about the state of the instance in the database.  If you want the SqlWorkflowPersistenceService to automatically pick up and run your newly created workflow then they need to be in the Executing state and they need to be NotBlocked.  When you first Create a workflow instance this is not the case.  I believe that you can simply call Start on your newly created instances in order to both change the instance's state as well as schedule the first work item if your desire is to have another machine watching the same DB to automatically pick up and run the workflows.

  • Anonymous
    August 27, 2008
    The comment has been removed

  • Anonymous
    August 27, 2008
    Bill Bassler, I'm not sure why you are seeing the behavior you mention above.  At the end of the this post please find the code for a console app which demonstrates the pattern I'm suggesting.  I've run this on my machine and with the throw commented out I get four rows in the database.  With the throw in place I get zero rows in the InstanceState table.TransactionScope sets up Transaction.Current for you so there is nothing special that needs to be done there.  Another place to check is your connection string.  I believe (but don't quote me on this) that there are settings which disable to usage of System.Transactions transactions for SQL connections.       static void Main(string[] args)       {           WorkflowRuntime runtime = new WorkflowRuntime();           SqlWorkflowPersistenceService persistence = new SqlWorkflowPersistenceService("Data Source=localhost\sqlexpress;Initial Catalog=WFTemp;Integrated Security=SSPI");           ManualWorkflowSchedulerService scheduler = new ManualWorkflowSchedulerService();           runtime.AddService(persistence);           runtime.AddService(scheduler);           try           {               using (TransactionScope scope = new TransactionScope())               {                   for (int i = 0; i < 4; i++)                   {                       WorkflowInstance instance = runtime.CreateWorkflow(typeof(MyWorkflow));                       instance.Start();                       instance.Unload();                   }                   // throw new ApplicationException();                   scope.Complete();               }           }           catch (Exception e)           {               Console.WriteLine("Caught exception: " + e);           }           Console.WriteLine("Done");           Console.ReadKey();       }       class MyWorkflow : SequenceActivity       {           public MyWorkflow()           {               this.CanModifyActivities = true;               CodeActivity code1 = new CodeActivity();               code1.ExecuteCode += new EventHandler(code1_ExecuteCode);               this.Activities.Add(code1);               CodeActivity code2 = new CodeActivity();               code2.ExecuteCode += new EventHandler(code2_ExecuteCode);               this.Activities.Add(code2);               this.CanModifyActivities = false;           }           void  code2_ExecuteCode(object sender, EventArgs e)           {               Console.WriteLine("Code2");           }           void  code1_ExecuteCode(object sender, EventArgs e)           {               Console.WriteLine("Code1");           }       }

  • Anonymous
    August 29, 2008
    After some further investigation I find that the 3rd party data access framework TransactionScope object, which is supposed to be a wrapper of (esTransactionScope, EntitiySpaces) TransactionScope object is the culprit. Once I changed to use ADO.net TranactionScope, which EntitySpaces also supports I get the appropriate rollback.The next problem that I see is that a new connection appears to be created from each instance of the workflow that's created. The pool is exhausted at 100 by default. The transaction scope must encapsulate the header record and any instance mapping table inserts. There only needs to be one connection. Not oine one for each workflow creation. Can this be acheived? Need something like the SharedConnectionWorkflowCommitBatchService to address this? Help please.using (TransactionScope scope = new TransactionScope())               {                   // Simulate updates to job header tables in hosting app.                   Case currentCase = new Case();                   currentCase.InitiationDate = DateTime.Now;                   currentCase.CardTransactionID = 1000;                   currentCase.InitiationUserID = 1;                   currentCase.Save();                   // Create batch of instances                   for (int i = 0; i < 250; i++)                   {                       WorkflowInstance instance = runtime.CreateWorkflow(typeof(Workflow1));                       instance.Unload();                       System.Diagnostics.Debug.WriteLine("Case: " + i.ToString());                   }                   //throw new ApplicationException();                   scope.Complete();              }

  • Anonymous
    August 29, 2008
    And Bill, now I must direct you to the MSDN workflow forums (http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=122&SiteID=1).  I'm not familiar enough with how to finesse the SQL persistence service to reuse connections across instances but someone on that forum should be able to help (or tell you if it is even possible).  This might actually be something that you can control through the connection string.Just in case you get a "that can't be done" answer from the forums: Worst case scenario you'll need to create your own persistence provider.  Because of the nature of your scenario it should be relatively simple to create a "BatchSaveWorkflowsPersistenceService" which simply implements the SaveInstanceState method and calls the appropriate stored procedure provided by SqlWorkflowPersistenceService.  Your implementation can reuse the connection to its heart's content.

  • Anonymous
    June 15, 2009
    PingBack from http://edebtsettlementprogram.info/story.php?id=23942

  • Anonymous
    June 15, 2009
    PingBack from http://mydebtconsolidator.info/story.php?id=7561

  • Anonymous
    June 16, 2009
    PingBack from http://fixmycrediteasily.info/story.php?id=266

  • Anonymous
    June 18, 2009
    PingBack from http://gardendecordesign.info/story.php?id=5619

  • Anonymous
    June 19, 2009
    PingBack from http://debtsolutionsnow.info/story.php?id=3527