Welcome to Windows Workflow Foundation (WF)
Top Tasks :

WF Community Bloggers

Browse by Tags

All Tags » .NET;WinFX;Workflow   (RSS)
Sorry, but there are no more tags available to filter with.

  • MsmqActivities v1.1 Released

    I’ve just uploaded a new release (v1.1) of my MSMQ Activities for Windows Workflow Foundation. This release does a few general fixes and polishes a few things here and there, but the largest change is a modification of the MsmqListenerService runtime service used by the MsmqReceiveActivity to listen to the MSMQ queues. This change is aimed at improving the situation I talked about on this past entry . Basically, this is something that will be very handy to ensure the activities work even when the hosting process dies unexpectedly and is restarted. As part of this release, a new interface is introduced in the component: IMsmqSubscriptionPersistenceService (sorry for the long name). This interface is used by the MsmqListenerService to handle persistence of all subscriptions created at runtime to a given MSMQ Queue. This interface has three methods that are consumed by the listener service: Persist(string host, MsmqSubscription subscription): This method should take the specified subscription and save it to a persistent storage, and is called when an MsmqReceiveActivity subscribes to a given MSMQ Queue. This method is called inside a System.Transactions.TransactionScope so that the listener service can abort the persistence if anything happens after that. IEnumerable<MsmqSubscription> LoadAll(string host): This method is called when the listener service is started (right after the WorkflowEngine is started on the process, in fact) to get a list of all subscriptions stored for the given host. For each subscription that is loaded, the listener service configures again a listener on the queue the subscription relates to. Remove(MsmqSubscription subscription): This method is called when a MsmqReceiveActivity removes a subscription to a queue. It should delete any record kept about the specified subscription in the persistent storage. The host argument to Persist() and LoadAll() is a very basic mechanism to allow you to keep a single persistent storage for subscriptions coming from multiple applications (i.e. multiple processes/machines hosting the WorkflowRuntime). The host name to use is specified when you create the MsmqListenerService instance either through an argument in a new constructor overload, or through the configuration file through the “hostname” attribute. If you do not specify a hostname, the value “default” will be used instead. Be careful to always set the hostname explicitly if you’re going to be sharing the persistence storage. Out of the box, I provide two implementations of the IMsmqSubscriptionPersistenceService interface: NullMsmqSusbcriptionPersistenceService: This is an empty implementation that doesn’t do anything. It can be used if you simply don’t want or need to support subscription persistence. SqlMsmqSubscriptionPersistenceService: This implementation stores all subscriptions as records in a table in a SQL Server database called “MsmqSubscriptions”. You can select which implementation to use by simply adding it to the Read More...
  • Event Activities and Persistent Subscriptions

    I've talked in past entries about event-driven activities (those implementing IEventActivity) in Windows Workflow Foundation and how to implement them. I discovered most of this stuff by going over all the samples available and a lot of spelunking around using Reflector while trying to create my MsmqActivities for WF. However, a recent question on the WF forums made me aware of a significant bug in my implementation. Let me try to describe from the beginning what the problem is: Normally, an event activity when used in an event context (say in one branch of a ListenActivity) works roughly like this: The ListenActivity will right at the beginning call the IEventActivity.Subscribe() method in your event activity forcing it to initialize any subscriptions needed. Normally this involves notifying a runtime service that the activity is interested in a given event and creating a WorkflowQueue for the notification. When the event occurs, the runtime service notifies the activities involved through the corresponding WorkflowQueue. This causes the IActivityEventListener<QueueEventArgs>.OnEvent() method of the ListenActivity to be called (since it is the one that subscribed to the event), which in turn asks our activity to execute (because it is the one that fired the event first). After this, the ListenActivity will call our IEventActivity.Unsubscribe() method to unsibscribe from our event (regardless of whether we triggered the event in the first place). Usually, this means we'll go out to the underlying runtime service to ask it to remove the subscription and delete the WorkflowQueue we were using. At any point in time during this process the workflow engine might decide to unload our workflow instance from memory and persist it using a configured persistence service (such as the built-in SqlWorkflowPersistenceService). In a lot of scenarios this will work correctly, because the WorkflowRuntime handles the persistence of the most important items: It will persist the workflow state and the state of each of the created activities (including our own). As part of this it will also "remember" which WorkflowQueues had been created and will even persist any contents of those queues, which is why anything you put on a WorkflowQueue should to be serializable. Looking at this with my own MsmqActivities, I noticed that if the host process hosting the workflow engine was kept alive, everything worked just fine, even if the individual workflow instances were unloaded and reloaded. However, if the hosting process was terminated after the workflow instances where unloaded from memory and it was started again (thus loading any persisted workflow instances), things might not work right. Specifically if the hosting process went down after IEventActivity.Subscribe() had been called but before the MsmqListenerService had received the message on the queue it was subscribed to, then when the workflow instance was loaded again by the runtime it wouldn't work because the Read More...
  • Custom TypeDescriptors and WF Activities

    While playing today with Windows Workflow Foundation I ran into something others might run into, and thought I would put it out there. I've been playing specifically with extending in various forms the design time support for a custom activity, and playing with dynamic/synthetized properties on them. Usually this is done through a custom ActivityDesigner that manipulates the properties collection in PreFilterProperties(), and sometimes via the IDynamicPropertyTypeProvider interface (which so far I've found rather superflous). Unfortunately, in this particular case that didn't do the trick, so I decided to go one step further and see if I could hack this by attaching a ICustomTypeDescriptor implementation to a custom activity via a custom TypeDescriptionProvider . This didn't go too well. Several problems I've run into so far include: All activities from a workflow disappearing on the designer (even though they are still there) Ocassionally crashing Visual Studio Weird compilation errors during validation, like this: error 348: Compilation failed. Specified method is not supported One of the issues at least seems to be caused by the fact that the CompositeActivity base class already has a custom type descriptor attached to it that you can't get at directly (since it's internal). I'll probably play with this some more, though from what I've seen so far it doesn't seem like it would accomplish what i was trying for even if I could work around the other issues. Windows Workflow Foundation , WF Read More...
  • WF Designer caching invalid XOML?

    While updating my MSMQ Activities for Windows Workflow Foundation, I ran into a strange issue with the WF designer when working with XOML-based workflows. The problem I was trying to solve was something like the following: The MsmqReceiveActivity had an attached dependency property called Label, as well as a regular .NET property around it. In code based workflows, that worked just fine. However, when designing XOML based workflows, it appeared to worked fine as well, but as soon as you closed the designer and tried opening the workflow again you'd get an error saying that the activity class needed to implement static GetLabel() and SetLabel() accessors. This was funky because the activity actually had those! Looking at the generated XOML code, it was doing something like this: < ns0:MsmqReceiveActivity x:Name = " ReceiveMessage " Queue = " {ActivityBind SampleWorkflow2,Path=QUEUE} " ns0:MsmqReceiveActivity.Label = " {ActivityBind SampleWorkflow2,Path=_labelReceived} " MessageType = " {x:Type TestApp.Customer} " Label = " {x:Null} " > < ns0:MsmqReceiveActivity.MessageReceived > < ActivityBind Name = " SampleWorkflow2 " Path = " _customerReceived " /> </ ns0:MsmqReceiveActivity.MessageReceived > </ ns0:MsmqReceiveActivity > Looking closely I finally discovered the issue: The problem was that the Label property was getting serialized twice! One was the attached dependency property itself (with the ActivityBind), the other was the normal .NET property! Knowing that, it was easy to fix, by just telling the designer not to serialize the regular .NET property: > [ SRDescription ( "Recv_Label" )] [ Category ( "Activity" )] [ ValidationOption ( ValidationOption .Optional)] [ DesignerSerializationVisibility ( DesignerSerializationVisibility .Hidden)] public string Label { get { return ( string ) base .GetValue(LabelProperty); } set { base .SetValue(LabelProperty, value ); } } Testing all of this is when I realized that everytime my activity serialized incorrectly in the XOML designer, and I caused the designer error when opening again, the designer would get "stuck" with the invalid XOML apparently getting it cached somewhere. Even if I manually went into the .xoml file and deleted the entire invalid block of code (completely removing the MsmqReceiveActivity instance), as soon as I opened the file again it would use the original, invalid XOML code. I actually had to close and restart Visual Studio to be able to fix the code. So, if this happens to you, restarting Visual Studio seems to do the trick. That said, I do wonder whether this "caching" going on was intentional or if it's a problem with the designer... > Read More...
  • A Custom UITypeEditor for Activity Properties

    As with many other technologies, the design time experience in Windows Workflow Foundation uses many of the same extensibility mechanisms found in other designers (such as the Windows Forms designer). One of those is the hability to provide custom type editors for properties by creating an UITypeEditor-derived class and then associating it with the property via the [Editor] attribute. Here's a sample UITypeEditor that will present an OpenFileDialog to choose a file name as the property value: // // FileSelectorTypeEditor.cs // // Author: // Tomas Restrepo (tomasr@mvps.org) // using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design; using System.Drawing; using System.Drawing.Design; using System.IO; using System.Text; using System.Windows.Forms; using System.Windows.Forms.Design; namespace Winterdom.Design.TypeEditors { /// <summary> /// Customer UITypeEditor that pops up a /// file selector dialog /// </summary> public class FileSelectorTypeEditor : UITypeEditor { public override UITypeEditorEditStyle GetEditStyle( ITypeDescriptorContext context) { if ( context == null || context.Instance == null ) return base .GetEditStyle(context); return UITypeEditorEditStyle .Modal; } public override object EditValue( ITypeDescriptorContext context, IServiceProvider provider, object value) { IWindowsFormsEditorService editorService; if ( context == null || context.Instance == null || provider == null ) return value; try { // get the editor service, just like in windows forms editorService = ( IWindowsFormsEditorService ) provider.GetService( typeof ( IWindowsFormsEditorService )); OpenFileDialog dlg = new OpenFileDialog (); dlg.Filter = "All Files (*.*)|*.*" ; dlg.CheckFileExists = true ; string filename = ( string )value; if ( ! File .Exists(filename) ) filename = null ; dlg.FileName = filename; using ( dlg ) { DialogResult res = dlg.ShowDialog(); if ( res == DialogResult .OK ) { filename = dlg.FileName; } } return filename; } finally { editorService = null ; } } } // class FileSelectorTypeEditor You can then easily associate it with a property like this: [ Editor ( typeof ( FileSelectorTypeEditor ), typeof ( UITypeEditor ))] public string Filename { get { return _filename; } set { _filename = value ; } } One thing to watch out for, though, is that at least with the July CTP of WinFX, WF will completely ignore your custom UITypeEditor if it is defined in the same assembly as the activity using it. Don't know why, but make sure you define it in a separate assembly you reference, and it should work OK. Read More...
  • MsmqActivities Updated

    I just uploaded an updated version of my MSMQ Activities for Windows Workflow Foundation . You can download the updated code from here . Here are some of the changes: Updated to work with the July CTP of .NET FX 3.0 Added a new MsmqDirectReceiveActivity class. This one also allows you to receive a message from a queue, but it is not an Event-Driven activity; instead it will directly try to receive the message from the specified queue. This is useful when, for example, you need to receive the message inside of a transaction scope that contains other activities. A few bug fixes, including a fix for how the Label property of the receive activities was getting serialized in XAML which caused the designer to throw errors when reloading the workflow. Read More...
  • Make sure TrackingDatabase is up to date

    Just one tip in case it happens to you: If you're updating to the latest .NET FX 3.0 builds, and you're using Windows Workflow Foundation, make sure you update any tracking and persistence databases you're using to the latest schema [1]. I ran into this with a Tracking database I had created incorrectly with the WF Beta 2 schema, and was causing the WF runtime to hang/freeze as soon as I enabled the SqlTrackingService. [1] You'll find the necessary SQL Scripts to create your databases in the "%windir%\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN" folder Read More...

<July 2008>
SuMoTuWeThFrSa
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

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