<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>/bill's House O Insomnia&lt;img src="http://www.williamgryan.com/images/originalcuckoo.jpg" alt="Bill Ryan" /&gt; : Workflow</title><link>http://msmvps.com/blogs/williamryan/archive/tags/Workflow/default.aspx</link><description>Tags: Workflow</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>WF Persistence - Where [DataContract] != [Serializable]</title><link>http://msmvps.com/blogs/williamryan/archive/2008/11/01/wf-persistence-where-datacontract-serializable.aspx</link><pubDate>Sat, 01 Nov 2008 07:27:07 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1652742</guid><dc:creator>William</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/williamryan/rsscomments.aspx?PostID=1652742</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/williamryan/commentapi.aspx?PostID=1652742</wfw:comment><comments>http://msmvps.com/blogs/williamryan/archive/2008/11/01/wf-persistence-where-datacontract-serializable.aspx#comments</comments><description>&lt;p&gt;Let&amp;#39;s say you were using Workflow Foundation (WF) and Windows Communication Foundation (WCF). Assume you wanted to use WF&amp;#39;s Persistence mechanism (which requires types to be &lt;a href="http://msdn.microsoft.com/en-us/library/system.serializableattribute(VS.71).aspx"&gt;Serializable&lt;/a&gt;). And assume that all the objects you were using in the workflow were decorated with the &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx"&gt;[DataContract]&lt;/a&gt; attribute.&amp;nbsp; Would you expect any problems related to Serialization?&amp;nbsp; &lt;em&gt;(I can but to the chase really quickly here if you don&amp;#39;t want my belabored background information and explanation. If you&amp;#39;re creating a type to use w/ Workflow Foundation that will be saved via the Workflow Foundation Persistence Service which makes use of the &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.runtime.hosting.sqlworkflowpersistenceservice.aspx"&gt;SqlWorkflowPersistenceService&lt;/a&gt; class, marking the class as a &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx"&gt;[DataContract]&lt;/a&gt; alone will not work for WF&amp;#39;s persistence mechanism. It does make the class &lt;a href="http://msdn.microsoft.com/en-us/library/system.serializableattribute(VS.71).aspx"&gt;serializable&lt;/a&gt; in a literal sense and will suffice [provided you meet the other requirements of a &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx"&gt;[DataContract]&lt;/a&gt;  for WCF&amp;#39;s serialization needs, but it is insufficient for WF (see the References section at the end of this post for more details on WF Serialization) - so make sure you use the &lt;a href="http://msdn.microsoft.com/en-us/library/system.serializableattribute(VS.71).aspx"&gt;Serializable&lt;/a&gt; attribute on any type that&amp;#39;ll be consumed by the Persistence Service).&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;MSDN describes the &lt;/strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx"&gt;&lt;strong&gt;DataContract class&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; the following way:&lt;/strong&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p align="left"&gt;&lt;em&gt; Specifies that the type defines or implements a data contract and is serializable by a serializer, such as&amp;nbsp;&amp;nbsp; the &lt;/em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx"&gt;&lt;em&gt;DataContractSerializer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. To make their type &lt;a href="http://msdn.microsoft.com/en-us/library/system.serializableattribute(VS.71).aspx"&gt;serializable&lt;/a&gt;, type authors must define a data contract for their type.&lt;/em&gt; &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;If you spend a lot of time in WCF, you&amp;#39;d likely assume that b/c types decorated with the &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx"&gt;DataContract&lt;/a&gt; attribute would satisfy any requirement for the type to be &lt;a href="http://msdn.microsoft.com/en-us/library/system.serializableattribute(VS.71).aspx"&gt;Serializable&lt;/a&gt;.&amp;nbsp; But you&amp;#39;d likely be wrong. Yes, a type that is a &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx"&gt;[DataContract]&lt;/a&gt;&amp;nbsp; is serializable in the literal sense, but it&amp;#39;s serialized by the &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx"&gt;DataContractSerializer&lt;/a&gt; (see the &lt;em&gt;References&lt;/em&gt; section at the end of this post for more details on WF Serialization) &lt;p&gt;So why is this an issue and what do you do about it?&amp;nbsp; Often, non-trivial workflows span an amount of time that exceeds any given user&amp;#39;s session.&amp;nbsp; In fact, it&amp;#39;s not uncommon for a non-trivial workflow to span as much as 30 days.&amp;nbsp; Using a simple example, let&amp;#39;s say that you are writing a Workflow to manage new employees.&amp;nbsp; Further assume that there are several document requirements and that any deficiencies would result in severe penalties or liability risks.&amp;nbsp; Just to make it clear, assume that each of the following must be procured before a new employee can start working.&amp;nbsp; Further, assume that b/c of fees associated with each, if any previous one fails, that the whole process terminates (if someone&amp;#39;s reference checks don&amp;#39;t pass, there&amp;#39;s no need to spend the money for a full background investigation as you know you&amp;#39;re not going to hire them). [Also, this isn&amp;#39;t a post on workplace hiring guidelines and is solely used for illustration - no need to point out why &amp;#39;its bad business to drug test or whatever else]. &lt;ol&gt; &lt;li&gt;Employment Application&lt;/li&gt; &lt;li&gt;Proof of Citizenship or ability to work in the U.S.&lt;/li&gt; &lt;li&gt;State withholding form&lt;/li&gt; &lt;li&gt;Federal withholding form&lt;/li&gt; &lt;li&gt;Reference check&lt;/li&gt; &lt;li&gt;License check&lt;/li&gt; &lt;li&gt;Completed Drug Screen&lt;/li&gt; &lt;li&gt;Full Background check&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Implementation policies will vary from company to company but assume that all of these tasks wouldn&amp;#39;t be completed within the user session that first created the entity. If you couldn&amp;#39;t persist the workflow somehow and come back to it later, it would be of very little use.&amp;nbsp;&amp;nbsp; Workflow foundation provides an out-of-the-box solution named not surprisingly -&amp;nbsp; &lt;a href="http://msdn.microsoft.com/en-us/library/ms735722(VS.85).aspx"&gt;Windows Workflow Persistence Service&lt;/a&gt; to help with long running workflows&lt;/p&gt; &lt;p&gt;Since Workflow Foundation is still in its infancy in terms of user adoption, many shops don&amp;#39;t have well established design rules in place specifically for Workflow items.&amp;nbsp; This can have some profound (although easily addressed in most cases) effects on Workflow development. It&amp;#39;s common for a workflow to start out small in terms of steps and happen relatively quickly.&amp;nbsp; When this is the case, there&amp;#39;s little need for a persistence mechanism for the workflow.&amp;nbsp; But as people get comfortable with WF and are willing to try more involved solutions, steps get added that often increase the time span the workflow could run to a point that&amp;#39;s longer than the user session.&amp;nbsp; For people new to WF, adding that first activity that&amp;#39;ll possibly span a large amount of time is the first time they actually think seriously about the persistence service. And that&amp;#39;s the point at which they often go back and try to retrofit things.&amp;nbsp; In many cases, the number of &amp;quot;things&amp;quot; will be fairly substantial so it&amp;#39;s quite easy to overlook something.&amp;nbsp; Once you implement the persistence service, you&amp;#39;ll typically go through the testing phase and make sure everything persist and can be retrieved correctly.&amp;nbsp; And this is the time serialization problems with show themselves - often in a manner that&amp;#39;s hard to isolate b/c the number of items involved.&amp;nbsp; &lt;/p&gt; &lt;p&gt; In some cases, if there&amp;#39;s a serialization problem, a fault will result.&amp;nbsp; &lt;a href="http://odetocode.com/Blogs/scott/archive/2007/01/24/9943.aspx"&gt;Unhandled faults&lt;/a&gt; in WF cause behavior that deviates from what you&amp;#39;d typically expect. So depending on your logging and tracing, you may or may not find the issue quickly. in many cases, you&amp;#39;ll find the fault is related to serialization and you&amp;#39;ll address it on the specific type, then go back and try to find every other type and make it &lt;a href="http://msdn.microsoft.com/en-us/library/system.serializableattribute(VS.71).aspx"&gt;serializable&lt;/a&gt; as well.&amp;nbsp; This is likely to be overkill though - b/c you&amp;#39;re likely to have some types that aren&amp;#39;t involved in anything that&amp;#39;s persisted and consequently don&amp;#39;t require persistence.&amp;nbsp; So you try to only make the items that will be persisted &lt;a href="http://msdn.microsoft.com/en-us/library/system.serializableattribute(VS.71).aspx"&gt;serializable&lt;/a&gt;. Until you get to the point where you&amp;#39;re addressing everything in the planning and design stages, you&amp;#39;re likely to run into situations like this and the only way out typically involves a lot of trial-and-error.&amp;nbsp; That&amp;#39;s why this post is relevant. If you go back and define each type that will be persisted as a &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx"&gt;[DataContract]&lt;/a&gt; , it&amp;#39;ll take you some time to do, may necessitate you adding new references to some projects and ultimately, after all that&amp;#39;s done, won&amp;#39;t fix the problem. The following type may work all day long when just dealing with WCF&amp;#39;s serialization requirements...&lt;/p&gt; &lt;p&gt;namespace Ger911.HCStandard.Core.Shared&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataContract]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class MatrixItem&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataMember]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public String EntityName { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataMember]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public String ContactName { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataMember]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Int32 BedCount { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataMember]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public String HospitalStatus { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataMember]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DateTime ModifiedDateTime { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;But unless you modify it like this, you&amp;#39;ll be in for some unpleasant surprises in WF:&lt;/p&gt; &lt;p&gt;namespace Ger911.HCStandard.Core.Shared&lt;br /&gt;{&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Serializable]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataContract]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class MatrixItem&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataMember]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public String EntityName { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataMember]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public String ContactName { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataMember]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Int32 BedCount { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataMember]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public String HospitalStatus { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [DataMember]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DateTime ModifiedDateTime { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;References:&lt;/p&gt; &lt;p&gt;Using &lt;a href="http://www.red-gate.com/products/reflector/"&gt;Red Gate&amp;#39;s Reflector&lt;/a&gt;, here&amp;#39;s what you&amp;#39;ll see under the hood of the &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.runtime.hosting.workflowpersistenceservice.aspx"&gt;WorkflowPesistenceService&lt;/a&gt; class&amp;#39;s &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.runtime.hosting.workflowpersistenceservice.restorefromdefaultserializedform.aspx"&gt;RestoreFromDefaultSerializedForm&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.runtime.hosting.workflowpersistenceservice.getdefaultserializedform.aspx"&gt;GetDefaultSerializedForm&lt;/a&gt;.&amp;nbsp; For further insight into this, use &lt;a href="http://www.red-gate.com/products/reflector/"&gt;Reflector&lt;/a&gt; and examine the &lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.runtime.hosting.sqlworkflowpersistenceservice.aspx"&gt;SqlWorkflowPersistenceService&lt;/a&gt;:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font size="3"&gt;&lt;strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.runtime.hosting.workflowpersistenceservice.restorefromdefaultserializedform.aspx"&gt;RestoreFromDefaultSerializedForm&lt;/a&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;protected static Activity RestoreFromDefaultSerializedForm(byte[] activityBytes, Activity outerActivity)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Activity activity;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DateTime now = DateTime.Now;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MemoryStream stream = new MemoryStream(activityBytes);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stream.Position = 0L;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (GZipStream stream2 = new GZipStream(stream, CompressionMode.Decompress, true))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; activity = Activity.Load(stream2, outerActivity);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TimeSpan span = (TimeSpan)(DateTime.Now - now);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, &amp;quot;Deserialized a {0} to length {1}. Took {2}.&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new object[] { activity, stream.Length, span }); return activity;&lt;br /&gt; } &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.workflow.runtime.hosting.workflowpersistenceservice.getdefaultserializedform.aspx"&gt;GetDefaultSerializedForm&lt;/a&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;protected static byte[] GetDefaultSerializedForm(Activity activity)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DateTime now = DateTime.Now;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (MemoryStream stream = new MemoryStream(0x2800))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stream.Position = 0L;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; activity.Save(stream);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (MemoryStream stream2 = new MemoryStream((int)stream.Length))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (GZipStream stream3 = new GZipStream(stream2, CompressionMode.Compress, true))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stream3.Write(stream.GetBuffer(), 0, (int)stream.Length);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ActivityExecutionContextInfo info = (ActivityExecutionContextInfo)activity.GetValue(Activity.ActivityExecutionContextInfoProperty);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TimeSpan span = (TimeSpan)(DateTime.Now - now);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, &amp;quot;Serialized a {0} with id {1} to length {2}. Took {3}.&amp;quot;, new object[] { info, info.ContextGuid, stream2.Length, span });&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] array = stream2.GetBuffer();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Array.Resize&amp;lt;byte&amp;gt;(ref array, Convert.ToInt32(stream2.Length));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return array;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx"&gt;&lt;font size="3"&gt;&lt;strong&gt;DataContractSerializer&lt;/strong&gt;&lt;/font&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;public sealed class DataContractSerializer : XmlObjectSerializer&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Fields&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private IDataContractSurrogate dataContractSurrogate;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private bool ignoreExtensionDataObject;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal Dictionary&amp;lt;XmlQualifiedName, DataContract&amp;gt; knownDataContracts;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private ReadOnlyCollection&amp;lt;Type&amp;gt; knownTypeCollection;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal IList&amp;lt;Type&amp;gt; knownTypeList;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int maxItemsInObjectGraph;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private bool needsContractNsAtRoot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private bool preserveObjectReferences;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private DataContract rootContract;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private XmlDictionaryString rootName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private XmlDictionaryString rootNamespace;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Type rootType;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Methods&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DataContractSerializer(Type type);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DataContractSerializer(Type type, IEnumerable&amp;lt;Type&amp;gt; knownTypes);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DataContractSerializer(Type type, string rootName, string rootNamespace);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DataContractSerializer(Type type, string rootName, string rootNamespace, IEnumerable&amp;lt;Type&amp;gt; knownTypes);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace, IEnumerable&amp;lt;Type&amp;gt; knownTypes);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DataContractSerializer(Type type, IEnumerable&amp;lt;Type&amp;gt; knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DataContractSerializer(Type type, string rootName, string rootNamespace, IEnumerable&amp;lt;Type&amp;gt; knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace, IEnumerable&amp;lt;Type&amp;gt; knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal static DataContract GetDataContract(DataContract declaredTypeContract, Type declaredType, Type objectType);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal override Type GetDeserializeType();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal override Type GetSerializeType(object graph);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal static Type GetSurrogatedType(IDataContractSurrogate dataContractSurrogate, Type type);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private void Initialize(Type type, IEnumerable&amp;lt;Type&amp;gt; knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private void Initialize(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace, IEnumerable&amp;lt;Type&amp;gt; knownTypes, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences, IDataContractSurrogate dataContractSurrogate);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal override bool InternalIsStartObject(XmlReaderDelegator reader);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal override object InternalReadObject(XmlReaderDelegator xmlReader, bool verifyObjectName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal override void InternalWriteEndObject(XmlWriterDelegator writer);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal override void InternalWriteObject(XmlWriterDelegator writer, object graph);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal override void InternalWriteObjectContent(XmlWriterDelegator writer, object graph);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal override void InternalWriteStartObject(XmlWriterDelegator writer, object graph);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override bool IsStartObject(XmlDictionaryReader reader);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override bool IsStartObject(XmlReader reader);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override object ReadObject(XmlReader reader);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override object ReadObject(XmlReader reader, bool verifyObjectName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal static object SurrogateToDataContractType(IDataContractSurrogate dataContractSurrogate, object oldObj, Type surrogatedDeclaredType, ref Type objType);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void WriteEndObject(XmlDictionaryWriter writer);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void WriteEndObject(XmlWriter writer);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void WriteObject(XmlWriter writer, object graph);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void WriteObjectContent(XmlDictionaryWriter writer, object graph);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void WriteObjectContent(XmlWriter writer, object graph);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void WriteStartObject(XmlDictionaryWriter writer, object graph);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void WriteStartObject(XmlWriter writer, object graph);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Properties&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IDataContractSurrogate DataContractSurrogate { get; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool IgnoreExtensionDataObject { get; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal Dictionary&amp;lt;XmlQualifiedName, DataContract&amp;gt; KnownDataContracts { get; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public ReadOnlyCollection&amp;lt;Type&amp;gt; KnownTypes { get; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int MaxItemsInObjectGraph { get; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool PreserveObjectReferences { get; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private DataContract RootContract { get; }&lt;br /&gt;}&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1652742" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/williamryan/archive/tags/.NET+General/default.aspx">.NET General</category><category domain="http://msmvps.com/blogs/williamryan/archive/tags/WCF/default.aspx">WCF</category><category domain="http://msmvps.com/blogs/williamryan/archive/tags/WIndows+Communication+Foundation/default.aspx">WIndows Communication Foundation</category><category domain="http://msmvps.com/blogs/williamryan/archive/tags/.NET+3.0+Framework/default.aspx">.NET 3.0 Framework</category><category domain="http://msmvps.com/blogs/williamryan/archive/tags/Workflow/default.aspx">Workflow</category><category domain="http://msmvps.com/blogs/williamryan/archive/tags/.NET+3.5+Framework/default.aspx">.NET 3.5 Framework</category></item><item><title>Sharepoint Training w/ Dunn Training and Sahil Malik</title><link>http://msmvps.com/blogs/williamryan/archive/2007/11/04/sharepoint-training-w-dunn-training-and-sahil-malik.aspx</link><pubDate>Sun, 04 Nov 2007 16:53:02 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1282314</guid><dc:creator>William</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/williamryan/rsscomments.aspx?PostID=1282314</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/williamryan/commentapi.aspx?PostID=1282314</wfw:comment><comments>http://msmvps.com/blogs/williamryan/archive/2007/11/04/sharepoint-training-w-dunn-training-and-sahil-malik.aspx#comments</comments><description>&lt;p&gt;Training is typically a large investment b/c it&amp;#39;s time intensive and trainers usually don&amp;#39;t work cheap. This weekend, out company hired &lt;a href="http://www.dunntraining.com" target="_blank"&gt;Dunn Training&lt;/a&gt; and &lt;a href="http://www.winsmarts.com" target="_blank"&gt;Sahil Malik&lt;/a&gt; to get us up to speed on Sharepoint.&amp;nbsp; I can say that dealing with &lt;a href="http://www.dunntraining.com" target="_blank"&gt;Dunn&lt;/a&gt; and &lt;a href="http://blah.winsmarts.com/" target="_blank"&gt;Sahil&lt;/a&gt; was like buying a Lexus except not nearly as expensive.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.dunntraining.com" target="_blank"&gt;Mark Dunn&lt;/a&gt; attended the training and was there&amp;nbsp; the whole time to help out. &lt;a href="http://blah.winsmarts.com/" target="_blank"&gt;Sahil&lt;/a&gt; arrived right on time and from start to finish, he covered virtually every aspect of Sharepoint that one could care about.&amp;nbsp; I consider both &lt;a href="http://www.dunntraining.com" target="_blank"&gt;Mark&lt;/a&gt; and &lt;a href="http://www.winsmarts.com" target="_blank"&gt;Sahil&lt;/a&gt; good friends of mine but if I wasn&amp;#39;t impressed with the training, I just wouldn&amp;#39;t mention it. A good portion of our office showed up and Mark was kind enough to let me bring Kim.&lt;/p&gt; &lt;p&gt;The first few hours showed you how to use Sharepoint to do most of the common activities using the UI. Later in the afternoon, we started getting into coding tasks.&amp;nbsp; If you read &lt;a href="http://www.amazon.com/Pro-ADO-NET-2-0-Sahil-Malik/dp/1590595122/ref=sr_1_1/104-5033081-6704718?ie=UTF8&amp;amp;s=books&amp;amp;qid=1194194359&amp;amp;sr=8-1" target="_blank"&gt;Sahil&amp;#39;s ADO.NET 2.0 book&lt;/a&gt; , you can tell the same guy that wrote that book built this courseware.&amp;nbsp; His stuff is thorough and fun and he keeps thing moving by keeping the laughs&amp;nbsp; rolling.&lt;/p&gt; &lt;p&gt;The first day was largely what you could call common Sharepoint tasks, today we&amp;#39;ve moved on to InfoPath and workflows.&amp;nbsp; Here&amp;#39;s an outline of the courseware if you happen to be interested in it:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;1. Introduction &lt;p&gt;2. Preparing a good SharePoint environment. &lt;blockquote&gt; &lt;p&gt;a. Development&lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;b. Production&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;3. SharePoint security &lt;blockquote&gt; &lt;p&gt;a. Search&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;4. Content Types - A better way to manage your data &lt;p&gt;5. Recap &lt;p&gt;6. Leveraging VSeWSS - developing in a team environment &lt;p&gt;7. SharePoint as a WCM. &lt;blockquote&gt; &lt;p&gt;a. W3C compliant sites.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;8. Writing Custom Web parts for SharePoint &lt;p&gt;9. Excel Services &lt;p&gt;10. InfoPath &lt;p&gt;11. Workflows in MOSS &lt;blockquote&gt; &lt;p&gt;a. Out of the box experience&lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;b. SharePoint designer based workflows&lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;c. Visual Studio based WFs&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;12. BDC &lt;p&gt;13. Administering and Monitoring SharePoint &lt;p&gt;&amp;nbsp; &lt;p&gt;To give you a feel for the audience, most of the folks were seasoned .NET developers.&amp;nbsp; A few were either purely or mainly DB admins or developers.&amp;nbsp; We had one technical writer and a tester.&amp;nbsp; A few of the devs were much more focused on Windows Forms as opposed to ASP.NET.&amp;nbsp; Only two of us had ever really done any Sharepoint development and only 4 of us had used Sharepoint 07 as an end user or dev. At the risk of sounding self-flattering, the group was pretty sharp but I would say that Sahil&amp;#39;s approach would have worked well for just about any group you put in front of him. &lt;p&gt;Personally, I was strongest with&amp;nbsp;three areas- Workflows , InfoPath and &lt;a href="http://www.amazon.com/Programming-Excel-Services-PRO-Developer-Bruney/dp/0735624070/ref=pd_bbs_sr_3/104-5033081-6704718?ie=UTF8&amp;amp;s=books&amp;amp;qid=1194194372&amp;amp;sr=8-3" target="_blank"&gt;Excel Services&lt;/a&gt;. I had been lead technical editor on &lt;a href="http://www.amazon.com/Programming-Excel-Services-PRO-Developer-Bruney/dp/0735624070/ref=pd_bbs_sr_3/104-5033081-6704718?ie=UTF8&amp;amp;s=books&amp;amp;qid=1194194372&amp;amp;sr=8-3" target="_blank"&gt;Alvin Bruney&amp;#39;s Excel Services&lt;/a&gt; book and have been a worflow junkie since they came out.&amp;nbsp; InfoPath is just plain cool although I frequently feel like both of us that use it are freaks b/c it&amp;#39;s hard to run into anyone that uses InfoPath.&amp;nbsp; In each aspect though, I definitely learned a few tricks.&amp;nbsp; Sahil&amp;#39;s instruction on BI and KPI&amp;#39;s within Excel was a big hit and I think everyone pretty much found the presentation very impressive. &lt;p&gt;The InfoPath coverage was pretty darned cool too and was pretty easy to pick up on even though hardly anyone had used it before.&amp;nbsp; Seeing what you can do with it and how easy it was proves that many tasks that required a developer to build before can be done by a power user although I suspect it&amp;#39;s going to open many new doors for developers as power uses start digging into it. &lt;p&gt;So throughout the training, Sahil pointed out real world issues you&amp;#39;ll end up dealing with and no doubt saved us from many pitfalls. In fact, the real world aspect is precisely one of the things that made this training so good.&amp;nbsp; He wasn&amp;#39;t afraid to point out that not everything is perfect with respect to Sharepoint and went one step up by giving us resources to work arounds for such problems. &lt;p&gt;Training is a pretty big investment in terms of time and money. There&amp;#39;s no shortage of snake oil peddlers offering to help you &lt;a href="http://www.learnasp.com" target="_blank"&gt;LearnAsp&lt;/a&gt; or learn some other product, the type of trainers who put a lot of effort into blowing their own horns but who aren&amp;#39;t welcome back to any more work for people they&amp;#39;ve trained or worked for in the past.&amp;nbsp;&amp;nbsp; Good training companies and trainers are hard to come by and before making an investment, you should really look around and talk to people that have dealt with the company and the trainer. Mark Dunn&amp;#39;s company has the reputation they do b/c they&amp;#39;ve been around for a while and he is very picky about who deals with him.&amp;nbsp; Search the internet high and low and you won&amp;#39;t find anything non-flattering about Mark Dunn or his people. You wont&amp;#39; find a bunch of marketing speil and grandiose self-promotion or claims on his site b/c his customers do the advertising for him.&amp;nbsp;&amp;nbsp;In fact, we regularly use Mark Dunn&amp;#39;s training for a whole variety of products and everything has always been top notch.&amp;nbsp; I know Sahil is booked up for quite a while but if you&amp;#39;re looking for unequalled Sharepoint training, you should give &lt;a href="http://www.winsmarts.com" target="_blank"&gt;him&lt;/a&gt; or &lt;a href="http://www.dunntraining.com" target="_blank"&gt;Mark&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; a call. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1282314" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/williamryan/archive/tags/Workflow/default.aspx">Workflow</category><category domain="http://msmvps.com/blogs/williamryan/archive/tags/InfoPath/default.aspx">InfoPath</category><category domain="http://msmvps.com/blogs/williamryan/archive/tags/Training+Courses/default.aspx">Training Courses</category><category domain="http://msmvps.com/blogs/williamryan/archive/tags/Sharepoint/default.aspx">Sharepoint</category></item></channel></rss>