Welcome to Windows Workflow Foundation (WF)
Top Tasks :

WF Community Bloggers

Browse by Tags

All Tags » WinFX;Workflow   (RSS)

  • Programming Windows Workflow Foundation

    I got a review copy of K. Scott Allen 's " Programming Windows Workflow Foundation: Practical WF Techniques and Examples using XAML and C# " book and I just finished reading it recently, and wanted to take a moment to mention my opinion about it. First of all, I'm probably not quite Scott's target audience, seeing how I was already familiar with WF before getting into the book. From my point of view, the book aims to provide a quick introduction to what WF is and how to get started programming it. In that aspect, I think it does a pretty good job. The book starts by quickly introducing what WF and what it is composed of (the runtime, activities, designer, XAML and so on). Chapter 2 then talks in a bit more detail about how to create and design workflows, covering both the principal aspects of how the VS designer works, as well as writing workflows in code and XAML. But this chapter also goes a bit further and covers using the workflow compiler both from the command line (wfc.exe) as well as programmatically and XAML workflow activation. Chapter 3 is dedicated to writing sequential workflows, though it also covers basic host <-> workflow communication using the workflow runtime events, workflow parameters and external data services. The latter are taken up in more detail in chapter 4, which covers most of the basic activities in the base activity library. Chapter 5 introduces how to write custom activities. While the cover here is somewhat light (as expected given the breath of the topic), Scott does quickly cover important topics like activity binding and dependency properties and gives a quick look to readers of how to write custom activity designers and validators. Chapter 6 covers the hosting facilities in WF, including how to correctly use the WorkflowRuntime class, and all the built-in runtime services, including scheduling, persistence and tracking. Chapter 7 covers State-Machine workflows, including some simple examples of how to interact with the workflow from the host (like quering possible transitions from the current state). Chapter 8 covers host <-> workflow communication in detail, including the use of correlation tokens, role authorization and an explanation of workflow queues. Finally, Chapter 9 covers the rules engine in WF and using code and rule conditions in activities. As I said earlier, I'm probably not the the target reader for the book. Many of my readers probably won't also, so if you're looking for a comprehensive, in depth look at WF, you'll want to find some other source. However, if you are not familiar with WF yet, I believe Scott's book is a pretty good place to start. Here's why: The book is short, about 230 pages. Most people should be able to go through the book pretty quickly. Scott's writing is very much to my liking. He's direct, goes straight to the point without any B.S. and he's style is pretty engaging overall, so you won't get easily bored. Chapters are also very reasonably paced and good in length, Read More...
  • WF Tracking Services Explained

    Two new articles just got published to MSDN covering the Tracking facilities in Windows Workflow Foundation in great detail. The first one is " Windows Workflow Foundation: Tracking Services Introduction ", by David Gristwood, and provides a high-level introduction to what Tracking is and how it works in WF. It also shows how to instrument (add tracking) to a workflow and a brief example of how to use SqlTrackingQuery on your app to read the information written by the workflow tracking service. Towards the end, the article discusses Tracking Profiles and what they do. The second article is " Windows Workflow Foundation: Tracking Services Deep Dive " by Ranjesh Jaganathan, and this one focuses on the underpinings of the tracking facilities. One thing I liked here was the whole discussion about how profiles, trackpoints and locations are related to one another, as they provide a clear overview of how it works for anyone wanting to create custom tracking profiles, as well as how to use Extracts in your trackpoints to extract the data you want tracked from your workflow and activity instances. Technorati tags: Windows Workflow Foundation , WF , Tracking Read More...
  • Updated SqlTrackingQuerySample

    I just uploaded an updated version of the SqlTrackingQuery sample application I had created in January. I added no new functionality, just cleaned it up a little and now it compiles cleanly and works against the .NET FX 3.0 RC1 release. Windows Workflow Foundation , WF , SqlTrackingQuery , .NET Read More...
  • A Discussion on Workflow Persistence

    I've been having a discussion with Jon Flanders on the WF forums regarding some of the behaviors and semantics of how Workflow persistence works, particularly in regards of how and when workflow persistence and loading/unloading might happen and how it may affect custom event activities. Lots of good stuff there to ponder and gave me a chance to clarify a few issues I was unsure about. Thanks to Jon for taking the time to respond to my lots of questions Windows Workflow Foundation , WF , Persistence Read More...
  • Paul Andrews on the WF-not-a-toy Department

    Paul Andrews , WF Product Manager, has posted a response here on Harry Pierson's comments about the Toy-Nature of some of the Windows Workflow Foundation built-in services. Worth checking out to see a different perspective. Windows Workflow Foundation , WF Read More...
  • Runtime Services in App.Config in WF

    In Windows Workflow Foundation, you have two different ways of adding runtime services to the Workflow Engine: Through code, by using the AddService() method of the WorkflowRuntime class Through the application configuration file, by adding an entry to the <services/> tag. The latter is possible not only for the default services built into WF, like the SqlWorkflowPersistenceService , but also for your own ones; you just have to make sure you specify the correct type. You might have noticed that some of the service take extra parameters on the configuration file. For example, for the SqlWorkflowPersistenceService entry you can configure parameters like the ConnectionString, IsTransactional and so on. What may not be so obvious is that you can do the same thing for your own services and it's very easy! All you have to do is provide a constructor to your service class that takes a NameValueCollection as an argument; this collection will then have any named parameters that were included in the configuration entry. So, to keep in mind: Add your service to the configuration entry; each parameter is added as an attribute in the corresponding <add/> tag. For example: <add type="..." ConnectionString="...."/> Add alternate constructor to your service class with a NameValueCollection argument Extract named parameters from the NameValueCollection as needed to initialize your runtime service. Windows Workflow Foundation , WF Read More...
  • Things to know about WF

    Harry Pierson comments here and here about "stuff he didn't know about WF". Pay attention; some good tidbits of knowledge you'll find in there. Pay particular attention when he says which features of WF as implemented on V1 are "toys"; it will save you a lot of grief down the road. This is something that, as much as I like WF, I feel very strongly about, and I've had some discussions (not very succesful, mind you) on this topic in the past. I understand the fact that there are limitations on what could be implemented for a V1 product, and I do understand that because of the extensible and host-agnostic architecture of WF it was difficult to provide anymore out of the box for V1. I do fully recognize the goodness in the WF architecture (there is a lot to like, really). However, that was never my point. You know, it's fine if that was the intention, really. What I really don't like is that if indeed those services were merely examples/toys intented to show they should have never been part of the core product in the first place. As Harry correctly points out, they should've been samples included in the SDK will full source code (what good is an example binary assembly with no code, reflector notwithstanding?). Making them part of the core product is, frankly, deceiving and will cause many people to think they are production ready services they can fully rely on for real world scenarios (and yes, that includes things like multi-server/cluster/load-balanced deployments and the like; those are must-have features for a product of this kind, imho), particularly since the documentation doesn't say outright what the limitations of them are. It never hurts to ask again Windows Workflow Foundation , WF Read More...
  • DependencyProperties and Default Values

    if you've ever implemented design time support for a component or control in .NET, then you're probably familiar with the [DefaultValue] attribute, which allows the component developer to tell the designer what the default value for a given property is so that the "Reset" option in the property grid is enabled and knows to what default value to "reset" the property to when invoked. You also probably know that it's your responsability to initialize the property to the default value on your component's constructor so that it matches what you specified in the [DefaultValue] attribute, otherwise the user will get somewhat unexpected results. When working with Windows Workflow Foundation (and WPF, I imagine), you can certainly use the [DefaultValue] attribute in your custom activity properties, and it works just like in Windows Forms or ASP.NET. However, in WF you'll use Dependency Properties a lot, and you might notice that when you register a dependency property you can also specify a default value through the PropertyMetadata parameter. I initially thought they would just do the same thing. I was wrong, however, and they are not the same: When you specify a default value through PropertyMetadata, that value is used to physically initiallze the dependency property, so there's no need for you to actually initialize the property to the correct value in the activity's constructor. The default value specified through the PropertyMetadata is not taken into account by the design-time infrastructure, unlike the [DefaultValue] attribute. So, it seems that, again, both default value options are actually complementary and you should use both to get the full effect. That said, this gives me little reason to specify default values through the PropertyMetadata instance, when initializing the property in the constructor is just clearer (to me at least). Thanks to Patrick in the WF forums for getting me look at this closer! WF , Windows Workflow Foundation , DependencyProperty Read More...
  • Preventing an Activity from being a Child of Itself

    Someone asked an interesting question on the Windows Workflow Foundation forums regarding how to prevent a custom composite activity from being a direct/indirect child of itself, similar to how the TransactionScopeActivity does. However, he wanted to be able to control this in the WF designer, and not just using a custom activity validator like the TransactionScopeActivity does. After looking a bit, I came to the conclusion that there's no 100% sure way of doing this using the current WF designer bits. The problem is that basically you get pretty good notifications in a composite activity designer when something happens to your children, but very little in the way of what happens further down the activity tree. That said, you can control some of the most common scenarios directly, and leave some corner cases to an ActivityValidator. In particular, one can fairly easily cover the following scenarios: You can prevent the user from adding a direct child of the same type You can prevent the user from copy-pasting/dragging a direct composite activity child that contains an activity of the same as a direct/indirect child (i.e. you can prevent the user from dragging a sequence activity containing one of your activities into your activity). You can prevent an instance of your activity being added anywhere there's an activity of the same type as a parent/grandparent. Here's a sample ActivityDesigner that covers these three scenarios: public class ParentActivityDesigner : SequenceDesigner { /// <summary> /// Verify that the activities /// being inserted are not and don't contain /// a ParentActivity as a child. /// </summary> /// <param name="insertLocation"></param> /// <param name="activitiesToInsert"></param> /// <returns></returns> public override bool CanInsertActivities(HitTestInfo insertLocation, System.Collections.ObjectModel.ReadOnlyCollection<Activity> activitiesToInsert) { bool canDo = base .CanInsertActivities(insertLocation, activitiesToInsert); bool contains = ContainsParentActivity(activitiesToInsert); return canDo && !contains; } private bool ContainsParentActivity(IEnumerable<Activity> activities) { bool found = false ; foreach ( Activity act in activities ) { if ( act is ParentActivity ) found = true ; else { CompositeActivity composite = act as CompositeActivity; if ( composite != null ) { found = ContainsParentActivity(composite.Activities); } } if ( found ) return true ; } return false ; } /// <summary> /// Verify that in the parent chain where /// we are going to be inserted there isn't any /// other ParentActivity anywhere /// </summary> /// <param name="parentActivityDesigner"></param> /// <returns></returns> public override bool CanBeParentedTo(CompositeActivityDesigner parentActivityDesigner) { bool canDo = base .CanBeParentedTo(parentActivityDesigner); Activity parent = parentActivityDesigner.Activity; while ( parent != null ) { Read More...
  • Adding SmartTag Verbs to an Activity Designer

    Here's a small sample on how to add a new Verb and another SmartTag option to your custom Activity in the Windows Workflow Designer. Adding a new context-menu option to your activity is fairly easy and intuitive: You just need to create a new instance of the ActivityDesignerVerb class when your custom ActivityDesigner-derived class in initialized and add it to the Verbs collection. Adding a new SmartTag option is a little bit more work. SmartTag options are also ActivityDesignerVerb instances; however, configured SmartTags are returned by the SmartTagVerb property as a readonly collection. To add a new one, you need to override this property and return you own collection instead. Here's a small code sample that adds a single new "Save Image" Verb to right-click menu as well as adding a SmartTag for it: Technorati: WF , Windows Workflow Foundation , ActivityDesigner Read More...
  • Filtering Child Activities on a Composite Activity

    If you're creating a custom composite activity, you might need to restrict whether a given activity can be inserted as a child at a specific point of your composite activity when working on the Workflow Designer. Fortunately, this is actually fairly easy using the designer facilities in Windows Workflow Foundation. Let's quickly sample this by building a custom CodeFirstSequentialActivity, which is a simple sequential composite activity that requires that the first child activity in the sequence is a CodeActivity. Other than that, any other type of activity can be a child. First, we'll create a custom designer class for our activity, which we'll inherit from the SequenceDesigner class. In it, we'll override the CanInsertActivities method, in which we'll do a simple test: If the insertion point is the first one on our composite activities, then we'll check that the first activity being dropped/inserted is indeed a CodeFirstActivity, and, if so, just return false to block the designer from inserting the child activities: .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } public class CodeFirstSequentialActivityDesigner : SequenceDesigner { public override bool CanInsertActivities(HitTestInfo insertLocation, System.Collections.ObjectModel.ReadOnlyCollection<Activity> activitiesToInsert) { bool canDo = base .CanInsertActivities(insertLocation, activitiesToInsert); CompositeActivity theActivity = Activity as CompositeActivity; if ( theActivity != null ) { // first activity in can only be a CodeActivity if ( insertLocation.MapToIndex() == 0 ) { if ( !(activitiesToInsert[0] is CodeActivity) ) { return false ; } } } return canDo; } } Then, it's just a matter of associating our custom designer with our activity: .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } [Designer( typeof (CodeFirstSequentialActivityDesigner))] Read More...
  • Updated MsmqActivities now on Activity Library

    With a little help from Matthew Winkler , I now have added my recently updated MSMQ Activities for Windows Workflow Foundation posted on the Activity Library over at the WF community site . Thanks! Read More...
  • Spawned Contexts and Activity Binding

    A few weeks ago, there was a post on the Advanced Workflow blog (an excellent resource, which I recommend you take a look at) about spawned contexts and how it affects activities (or rather, code related to activities) nested inside activities such as Replicator, While and so on. This is an issue that can be quite confusing and it's easy to write code that won't work correctly under these circumstances (one of the dangers of writing too much code behind your workflow, I'd say). I've seen a few posts on the Windows Workflow forums from people that have been bitten by this issue, such as this one , and it got me thinking about whether using Activity Binds instead of directly modifying properties of activities in code (event handlers) might simplify this. As far as I can tell, it indeed works just fine under beta 2, and it seems to me like it can lead to a slightly more elegant solution than what I proposed as the solution for that particular post. Here's a similar example that instead defines a read-only property on the workflow class that returns the current member of an enumerator over the collection and then simply binds the relevant property of the activity in the While loop to the workflow property. Works much nicer, I think. private List < MemberInfo > members; private IEnumerator < MemberInfo > enumerator; public MemberInfo CurrentMember { get { return enumerator . Current; } } public Sample2() { InitializeComponent(); members = MemberInfo . GetMembers(); enumerator = members . GetEnumerator(); } private void WhileCondition( object sender, ConditionalEventArgs e) { e . Result = enumerator . MoveNext(); } You can see the code for the example here . Sample1.cs contains the original proposed solution, while Sample2.cs contains the new one using binding. That said, I'm still not totally happy with it. It still requires some code to put everything together and it's not quite as "declarative" as I'd like... Read More...
  • Simple WF designer customizations

    You can do a lot of customizations on how the Windows Workflow Foundation designer will present your custom activities to the user with relatively minor work. For example, you can change the default text that gets shown on the activity (instead of the default which is the activity name), change the icon that is associated with the activity or change the size or internal alignment of text and icon. You can do all of this without needing to step in and handle the painting of your activity in the designer yourself, which makes it quite a bit simpler. To do this, you'll want to create a custom ActivityDesigner-derived class and set or override its methods and properties as necessary. The most interesting properties here to manipulate are: Image: Contains the bitmap that is shown as part of your activity of your designer Text: contains the text that is displayed in the activity designer. By default, this will be the name given in the designer to the activity inside the workflow. Size: Defines the size that your activity will have in the designer. ImageRectangle, TextRectangle: These especify the rectangle where the image and text will be drawn at inside your activities. One thing to keep in mind when changing these is that they are specified in absolute coordinates inside the activity designer, not as relative to your activity's position in it. This means you'll want to calculate them based on the rectangle specified by the Bounds property of your activity designer. You'll also probably want to implement your own ActivityDesignerThem-derived class and override there the colors and formats used by the workflow designer to paint your activity, such as what gradient colors or back color you want to use, what text color and so on. Here's an example of a trivial activity whose designer draws it as a rounded square, with a larger icon on top and the text of the bottom: // // ConsoleActivity.cs // // Author: // Tomas Restrepo (tomasr@mvps.org) // using System; using System . ComponentModel; using System . ComponentModel . Design; using System . Drawing; using System . Drawing . Drawing2D; using System . Workflow; using System . Workflow . Activities; using System . Workflow . ComponentModel; using System . Workflow . ComponentModel . Design; namespace CustomDesignerShapeDemo { [ Designer ( typeof ( ConsoleActivityDesigner ), typeof ( IDesigner ))] public class ConsoleActivity : Activity { public static readonly DependencyProperty TextProperty = DependencyProperty . Register( "Text" , typeof ( string ), typeof ( ConsoleActivity )); /// <summary> /// Text to write to the console /// </summary> public string Text { get { return ( string ) base. GetValue(TextProperty); } set { base. SetValue(TextProperty, value ); } } protected override ActivityExecutionStatus Execute( ActivityExecutionContext executionContext) { Console . WriteLine(Text); return ActivityExecutionStatus . Closed; } } // class ConsoleActivity /// <summary> /// Customize the activity's Read More...
  • WF Event Activities (2)

    In a previous post I introduced event activities in Windows Workflow Foundation and what were the basics of how to create one. Now that we know which interfaces we need to implement, let's see now how to actually implement one. In a regular activity, the basic lifetime is fairly simple: you would basically override the Execute() method, do your work and return ActivityExecutionStatus.Closed. If you needed to do your work asynchronously, you'd return ActivityExecutionStatus.Executing, and then eventually report your status as Closed. For asynchronous activities, you'd probably want to override Cancel(), as well. Of course, let us not forget Initialize() which will be the first thing to execute. The same sequence of events applies to an Event Activity. Almost. This is because there are other methods that are called interleaved with the regular Activity methods which are important. Furthermore, you ideally want your activity to be able to execute in a regular scenario as well as inside an EventDrivenActivity, while reusing as much of your code as possible between the two possible execution paths. The basic sequence of things for an Event Activity inside an EventDrivenActivity is a little bit different. Here's a quick review of the workflow that occurs: Initialize() is called on your activity, as usual IEventActivity.Subscribe() is called on your activity by your parent EventDrivenActivity Your parent EventDrivenActivity is notified of your event through its IEventActivityListener<QueueEventArgs>.OnEvent implementation. IEventActivity.Unsubscribe() is called on your activity by your parent EventDrivenActivity Execute() is called Let us look now then at what you would do in each of these steps to ensure your Event Activity works and that you can reuse most of the code in both scenarios: 1 When Initialize() is called, do anything you need to initialize your activity. This is also a good place to generate a unique name for the WorkflowQueue you'll use later to communicate with your runtime service (a GUID is a good choice). 2 Your parent EventDrivenActivity subscribes to events on your activity's workflow queue by calling IEventActivity.Subscribe() on your instance. This means that it will be your parent activity which will get notified when something happens on the WorkflowQueue instance that you created to communicate with your runtime service, and not your own activity. This is the reason why IEventActivityListener<QueueEventArgs>.OnEvent will not get called when you are inside an EventDrivenActivity, but you'll still want to implement it to simplify your code when running as a regular activity. Normally, here all you would do is ask your runtime service to do an operation from you and to put the result into a workflow queue you created for this piurpose. You'd then subscribe your parent activity in your Subscribe() implementation to the QueueItemAvailable event of your workflow queue, by using WorkflowQueuingService.RegisterForQueueItemAvailable(). Read More...
More Posts Next page »

<July 2008>
SuMoTuWeThFrSa
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

Copyright © 2006 Microsoft Corporation. All Rights Reserved. | Terms of Use | Privacy Statement | Contact Us