WF and Serialization Part One

This is part one of a two part post (because I know it is going to be too long to be comfortable as a single post) on Workflow and Serialization.

As a starting point, the WF Runtime is built to handle serialization of Activities.  The most common form of serialization in WF is persistence.  If you are running workflows inside of WF and you add a WorkflowPersistenceService to the Runtime, the Runtime will use this service whenever it determines that the workflow should persist.  This enables some interesting scenarios like load-balancing, where a workflow can be persisted on one machine and then be brought back to life on another machine (as in an ASP.NET web farm).

Persistence of Workflows is fairly determinilistic, they persist when:

1) The host calls WorkflowInstance.Unload or TryUnload (i.e. the host wants them to persist).

2) The end of a TransactionScopeActivity or an Activity that has the PersistOnClose attribute on it.

3) When the workflow idles (assuming the WorkflowPersistenceService tells the runtime to persist for that Activity type).

4) When an ActivityExecutionContext closes (sometimes, more on this in Part Two – thanks to Dharma http://www.dharmashukla.com/ for catching this).

Now – one of the issues people have been running into with WF and persistence is that when you first start designing your WF system, you generally don’t add a WorkflowPersistenceService at the beginning.  The issue that can trip you up here is that if you are adding fields or properties to your Workflow you want to think about Serialization upfront.  In fact, the parameters that you can pass to WorkflowRuntime.CreateWorkflow are not serialized (unlike parameters you pass when you do ExternalDataExchangeService related communication), so it is fairly easy to add a property to your workflow that isn’t serializable and your workflow works fine, up until the time you add a WorkflowPersistenceService.  When you add the WorkflowPersistenceService you will get a serialization exception when your workflow tries to persist.  This of course is problematic.

So what can you do to deal with objects your workflow might need to have as internal state which aren’t serializable if you need to use the WorkflowPersistenceService.

So the choices branch here.  If you wrote the type yourself, you can always add the Serializable attribute (or implement ISerializable) to your type.  This certainly solves the problem, assuming that this type can be serialized, which it might not be depending on the fields that this type has.

Another option is to add the NonSerialized attribute to any fields (either on the Workflow or your child types) that you can live without.  This option works whether or not you wrote the type the fields represent.

Now – if you didn’t write the type in question that isn’t serializable *and* you need to keep that object around during serialization (that is you need the state this object has and can’t easily re-create it after de-serialization), you have another option (this options is actually used by the WorkflowRuntime to serialize Activity – which if you look at the definition doesn’t have the Serializable attribute or implement the ISerializable interface).

The option relates to the .NET runtime’s serialization system. You can find information about this system by reading this article  by Jeff Richter.  By registering a SerializationSurrogate, you can allow an non-serializable type to be serialized and deserialized, which of course would solve the problem at hand.

I won’t go into the technical details as much as show you how to register your own ISerializationSurrogate to integrate with WF.  Let’s assume your workflow has a non-serializable type as a property – let’s assume something simple like a Point (of course this type could easily be serializable – let’s assume we didn’t write it and the author didn’t consider this issue).

public class Point
{
public Point(int px,int py)
{

x = px;
y = py;
}
public int x;
public int y;
}

 

So assume our workflow has a proprerty of this type, of course everything will work fine until we add the WorkflowPersistenceService, at which time of course we’ll get a serialization exception.

To fix this problem we can create a SurrogateSelector, that when chained with the WF Runtime’s SurrogateSelector can be used to serialize the Point type for us.  So the first this we need to do is to write the SurrogateSelector and the SerializationSurrogate.  Here is a simple implementation for Point:

public class PointSurrogateSelector : SurrogateSelector
{
public override ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector)
{
if (type == typeof(Point))
{
selector = this;
return new PointSerializationSurrogate();
}
return base.GetSurrogate(type, context, out selector);
}
}
public class PointSerializationSurrogate : ISerializationSurrogate
{
[Serializable]
public class PointRef : IObjectReference
{
#region IObjectReference Members

public object GetRealObject(StreamingContext context)
{
Point p = new Point(x, y);
return p;
}
int x;
int y;

#endregion
}
#region ISerializationSurrogate Members

public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
Point p = obj as Point;
if (p == null)
{
throw new ArgumentException(“Invalid type”);

}
info.AddValue(“x”, p.x);
info.AddValue(“y”, p.y);
info.SetType(typeof(PointRef));
}

public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
throw new Exception(“The method or operation is not implemented.”);
}

#endregion
}

Next we need to chain this SurrogateSelector with the ActivitySurrogateSelector.  This can be done anywhere, but needs to be done before this workflow will be serialized, so I prefer to add this code in my Hosting layer before I start the WorkflowRuntime (although it can be added after the WorkflowRuntime starts as it isn’t a WorkflowService  – it just hooks into the .NET serialization infrastructure).  Here is the line of code that does that:

ActivitySurrogateSelector.Default.ChainSelector(new PointSurrogateSelector());

So here we are – at the end of part one, and we can now make nonserializable types serializable by registering a SurrogateSelector and SerializationSurrogate.  In Part Two I will talk about stategies you can use to reduce the size of your serialized workflows, as well as another related way to solve this problem (which was suggested to me by a student in my WF class last week – Faisal Alamgir from EDS ).

83 thoughts on “WF and Serialization Part One

  1. Looks like this is solving all the problems that BizTalk already solves when it comes to persisting flows. Whomever says that WF is a replacement for BizTalk is seriously misguided.

    Can’t wait to see BizTalk in its new WF clothes though! Would love to be able to change a BizTalk orchestration without having to go through the build/deploy cycle.

  2. Excellent info Jon. One thing that rather baffles me about WF is stuff like this: Sure, the runtime is pretty extensible, and yes, they support you changing most of the built-in services (such as creating your own persistence service that uses something different from serialization), but all of this comes at a cost, and one that, quite frankly, I’m not sure is all that wise: There is almost *no* built-in mechanism to check that you *don’t* make mistakes like this during design-time.

    While yeah, you might be able to work around stuff like this in your own workflows, what about you depending on third party activities that with unknown internal implementations? You really can’t trust them at all (meaning a rather larger set of tests). What about the holy grail of business users defining workflows from sets of custom, business-specific activities? impossible if they need to face simple yet highly annoying things like this?

  3. Tomas – I agree with you *except* they have also given us the validtion hooks to make sure this doesn’t happpen. If you are building that holy grail kind of application you are going to be controlling (tightly) the activities that can be added to your workflow.

    But I agree – certainly because of the extensibility there are more points at which you can really get bitten (and luckily in all of them I have found you can get yourself back out of trouble pretty easily).

  4. Jon,

    Ohh, I don’t mean the validation hooks are not there, as you say they are. My point was: how many people will first of all figure they *need* to use those hooks, what code to write and remember to run them on each activity/workflow they use? It sure as hell is not intuitive, and my guess is most people will find out about it the hard way (i.e. by loosing data/time in production), which will only make it all the more frustraring. It’s not so much a technical issue per se, but rather somewhat of a User (developer) Experience thing.

  5. My custom (developed using VS 2005) workflow runs on a Infoath form library and i wanna send infopath forms as an attchment in the mail to the users. I got the following exception:

    Type ‘System.Net.Mail.Attachment’ in Assembly ‘System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′ is not marked as serializable. Type ‘System.Net.Mail.Attachment’ in Assembly ‘System, Version=2.0.0.0, Culture=neutral, PublicKeyToke

    Then, i tried with surrogator classes and it made the attachment class serializable but other exception came up which is as follows:

    Type ‘Microsoft.SharePoint.SPFileStream’ in Assembly ‘Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c’ is not marked as serializable. Type ‘Microsoft.SharePoint.SPFileStream’ in Assembly ‘Microsoft.SharePoint, Version 1.0.0.0

    I am using the foolowing code to assign the attachment to the attchment property of the activity:

    SPFile File = TransmittalItem.File;

    Stream FileStream = File.OpenBinaryStream();

    Attachment FileAttachment = new Attachment(FileStream, @"application/xml");

    FileAttachment.Name = File.Name;

    Task.sendEmailActivity1_Attachment1 = FileAttachment;

    In this code i am nit using SPFileStream type anywhere.

    Any Ideas, how to do it?

  6. Many useful thing for download! Take it for free!
    <a href="http://meekassoc.com/board/forum.php?topic=nobuo-uematsu-feel-download">nobuo uematsu feel download</a>
    <a href="http://meekassoc.com/board/forum.php?topic=farting-preacher-5-download">farting preacher 5 download</a>
    <a href="http://meekassoc.com/board/forum.php?topic=kim-kardashian-ray-j-sex-tape-download">kim kardashian ray-j sex tape download</a>
    <a href="http://meekassoc.com/board/forum.php?topic=icq4-free-download">icq4 free download</a>
    <a href="http://meekassoc.com/board/forum.php?topic=free-sound-card-downloads">free sound card downloads</a>
    <a href="http://meekassoc.com/board/forum.php?topic=download-motorola-phone-tools">download motorola phone tools</a>
    <a href="http://meekassoc.com/board/forum.php?topic=window-xp-downloads">window xp downloads</a>
    <a href="http://meekassoc.com/board/forum.php?topic=kenshin-himura-mugen-download">kenshin himura mugen download</a>
    <a href="http://meekassoc.com/board/forum.php?topic=download-virtual-cat-game">download virtual cat game</a>
    <a href="http://meekassoc.com/board/forum.php?topic=download-movie-free">download movie free</a>
    <a href="http://meekassoc.com/board/forum.php?topic=download-hentai-videos">download hentai videos</a>
    <a href="http://meekassoc.com/board/forum.php?topic=motorola-mobile-phone-tools-download">motorola mobile phone tools download</a>
    <a href="http://meekassoc.com/board/forum.php?topic=download-paper-mario-64-rom">download paper mario 64 rom</a>
    <a href="http://meekassoc.com/board/forum.php?topic=free-download-mp3">free download mp3</a>
    <a href="http://meekassoc.com/board/forum.php?topic=software-synthesizer-program-downloads">software synthesizer program downloads</a>

  7. <a href="http://byronthaimassage.com/images/used/video.php?p=amature-porn-tube-sites">amature porn tube sites</a><br>
    <a href="http://byronthaimassage.com/images/used/video.php?p=best-free-porn-tubes-list">best free porn tubes list</a><br>
    <a href="http://byronthaimassage.com/images/used/video.php?p=amateurs-prostate-sex-free-tubes">amateurs prostate sex free tubes</a><br>
    <a href="http://byronthaimassage.com/images/used/video.php?p=adult-tube-middle-age-wife">adult tube middle age wife</a><br>
    <a href="http://byronthaimassage.com/images/used/video.php?p=candace-nicole-free-porn-tubes">candace nicole free porn tubes</a><br>
    <a href="http://byronthaimassage.com/images/used/video.php?p=black-you-tube-porn">black you tube porn</a><br>
    <a href="http://byronthaimassage.com/images/used/video.php?p=adult-female-pornstar-lovette-tube">adult female pornstar lovette tube</a><br>
    <a href="http://byronthaimassage.com/images/used/video.php?p=3d-sex-tube-compilation">3d sex tube compilation</a><br><a href="http://experience7.ca/en/jscss/tube/video.php?p=free-amatuer-teen-porn-tube">free amatuer teen porn tube</a><br>
    <a href="http://experience7.ca/en/jscss/tube/video.php?p=cruising-for-sex-on-u-tube">cruising for sex on u tube</a><br>
    <a href="http://experience7.ca/en/jscss/tube/video.php?p=free-anminal-sex-tube">free anminal sex tube</a><br>
    <a href="http://experience7.ca/en/jscss/tube/video.php?p=free-porn-tubes-clips">free porn tubes clips</a><br>
    <a href="http://experience7.ca/en/jscss/tube/video.php?p=deuxma-your-porn-tube">deuxma your porn tube</a><br>
    <a href="http://experience7.ca/en/jscss/tube/video.php?p=croco-tube-porn">croco tube porn</a><br>
    <a href="http://experience7.ca/en/jscss/tube/video.php?p=free-black-anal-sex-tubes">free black anal sex tubes</a><br>

    <a href="http://experience7.ca/en/jscss/tube/video.php?p=free-gay-sex-tube">free gay sex tube</a><br>
    <a href="http://experience7.ca/en/jscss/tube/video.php?p=free-gay-policeman-porn-tube">free gay policeman porn tube</a><br>
    <a href="http://experience7.ca/en/jscss/tube/video.php?p=free-porn-tube-taboo-movie-classic">free porn tube taboo movie classic</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=hot-anal-porn-babes-tube">hot anal porn babes tube</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=insest-sex-tubes">insest sex tubes</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=gold-tube-porn">gold tube porn</a><br>

    <a href="http://ppnf.org/img/avatar/video.php?p=free-young-fuck-old-porn-tube">free young fuck old porn tube</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=gay-12-inch-sport-sex-tube">gay 12 inch sport sex tube</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=hard-cor-porn-tube">hard cor porn tube</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=free-sex-tube-engines">free sex tube engines</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=hd-adult-tube-free">hd adult tube free</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=how-to-search-u-tube-porn">how to search u tube porn</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=japanese-asian-porn-tube">japanese asian porn tube</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=juliana-di-sex-tube">juliana di sex tube</a><br>
    <a href="http://ppnf.org/img/avatar/video.php?p=gay-adult-male-tube">gay adult male tube</a><br>

  8. http://www.erexion.org/products/viagra-jelly.htm?us=41-2 [url=http://www.erexion.org/products/kamagra.htm?us=41-2]kamagra[/url] <a href="http://www.erexion.org/products/levitra-professional.htm?us=41-2">levitra professional</a> <a href=http://www.erexion.org/products/kamagra-oral-jelly.htm?us=41-2>cheap kamagra oral jelly</a> [url="http://www.erexion.org/products/sublingual-cialis.htm?us=41-2"buy sublingual cialis[/url] [LINK http://www.erexion.org/products/sublingual-viagra.htm?us=41-2sublingual viagra[/LINK] vmxs

  9. http://www.erexion.org/products/revatio.htm?us=41-3 [url=http://www.erexion.org/products/provigrax.htm?us=41-3]cheap provigrax[/url] <a href="http://www.erexion.org/products/proscar.htm?us=41-3">cheap proscar</a> <a href=http://www.erexion.org/products/horny-goat-weed.htm?us=41-3>buy horny goat weed</a> [url="http://www.erexion.org/products/maxaman.htm?us=41-3"cheap maxaman[/url] [LINK http://www.erexion.org/products/speman.htm?us=41-3buy speman[/LINK] cpdg

  10. http://www.erexion.org/products/avodart.htm?us=41-4 [url=http://www.erexion.org/products/viagra-soft-tabs.htm?us=41-4]viagra soft tabs[/url] <a href="http://www.erexion.org/products/ed-discount-pack-3.htm?us=41-4">ed discount pack 3</a> <a href=http://www.erexion.org/products/brand-cialis.htm?us=41-4>brand cialis</a> [url="http://www.erexion.org/products/viagrx.htm?us=41-4"cheap viagrx[/url] [LINK http://www.erexion.org/products/casodex.htm?us=41-4buy casodex[/LINK] kulc

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>