Welcome to my blog on all things SharePoint. I have a range of articles that will interest you if you've made it as far as visiting my blog. I was awarded as an SharePoint MVP by Microsoft in July 2010. I currently live in New York and am an Enterprise Architect at AvePoint Inc.. I co founded www.NothingButSharePoint.com with Mark Miller in 2010.

MVP AwardJeremy Thake Profile Photo

Whitepapers

NBSP

Check out my articles on NothingButSharePoint.com

Solution Development in SharePoint 2007

This series was inspired by the chatter amongst SharePoint blogs on the best ways to approach customisations in SharePoint using Solutions.

Part 1 - Part 2 - Part 3 - Part 4 - Part 5 - Part 6 - Part 7 - Part 8

Leveraging the SharePoint Platform

This series was inspired by a discussion had with Andrew Coates at a Perth SharePoint User Group meeting. This then turned into a 6 part series on Arno Nell's SharePointMagazine.net web site.

Initial post - Part 1 - Part 2 - Part 3 - Part 4 - Part 5 - Part 6

Webcasts

I have recorded various web casts that I present at User Groups or just on a specific topic by request:
How ASP.NET Developers can leverage SharePoint webcast
SPSource Webcast: Reverse engineer Lists to ListTemplates and much more
SharePoint Development with Unit Testing webcast
Perth SharePoint UG Web Cast on approaches to deploying artefacts (SPSource)
More...


Podcasts

I have been interviewed about Leveraging the SharePoint Platform by the SharePoint Pod Show: listen here .

RSS Feed Feed your read!

Archives

November 2012 (6)
October 2012 (8)
September 2012 (4)
August 2012 (7)
July 2012 (13)
June 2012 (4)
March 2012 (1)
February 2012 (1)
January 2012 (5)
September 2011 (2)
August 2011 (1)
July 2011 (3)
June 2011 (7)
May 2011 (3)
April 2011 (3)
March 2011 (3)
February 2011 (2)
January 2011 (1)
December 2010 (4)
September 2010 (4)
July 2010 (5)
June 2010 (4)
May 2010 (6)
April 2010 (7)
March 2010 (5)
February 2010 (7)
January 2010 (3)
December 2009 (1)
November 2009 (6)
October 2009 (9)
September 2009 (7)
August 2009 (6)
July 2009 (13)
June 2009 (4)
May 2009 (12)
April 2009 (4)
March 2009 (4)
February 2009 (13)
January 2009 (4)
December 2008 (4)
November 2008 (11)
October 2008 (16)
September 2008 (4)
August 2008 (5)
July 2008 (4)
June 2008 (8)
May 2008 (5)
April 2008 (9)
March 2008 (5)
February 2008 (6)
January 2008 (1)
November 2007 (11)
October 2007 (8)
September 2007 (24)
August 2007 (5)
July 2007 (2)
May 2007 (1)
April 2007 (1)
March 2007 (1)
February 2007 (3)
January 2007 (4)
November 2006 (7)
October 2006 (7)
September 2006 (18)
August 2006 (14)
June 2006 (3)
May 2006 (8)
April 2006 (4)
March 2006 (38)
February 2006 (30)
January 2006 (2)
December 2005 (3)
November 2005 (28)
May 2005 (1)
April 2005 (5)
March 2005 (1)
November 2004 (1)
August 2004 (11)
July 2004 (1)
Failed to render control: An error occurred during a call to extension function 'createMonthUrl'. See InnerException for a complete description of the error.

Links

Tag Cloud

Ajax, Apple, DotNetNuke, Enterprise Content Management, Error Resolution, Gadgets, General, Governance, Microsoft .Net Development, Mobile, SharePoint, Sharepoint Business Forms, Sharepoint Business Intelligence, Sharepoint Collaboration, SharePoint Development, Sharepoint Enterprise Content Management, Sharepoint Enterprise Search, Sharepoint Portal, US Migration, Web 2.0, Workflow
May 182008

Empower Users to manage Workflow (Part 1)

I've repeatedly stated that there are certain areas of the SharePoint 2007 stack that are not true Enterprise level features. Workflow is one of them and various other bloggers and reports have stated this, my research links are a testimony to this.

I believe Microsoft have confused the SharePoint community by giving two options with SharePoint Designer (SPD) Workflows and Visual Studio (VS) Workflows. Furthermore, the fact that it is not a straightforward exercise to migrate a SPD Workflow to a VS Workflow. Both approaches have their pros and cons and they are both targeted at different audiences. The targeting is based on a marketing approach and aligns to Microsoft's "empowering users" Information Worker philosophy of late.
The danger of empowerment has a clear history of bad outcomes from the days of letting Business Users loose on a Network Share Drive to the more modern dangers of SharePoint Site Creation. One of my own personal gripes at SharePoint is the lack of an OOTB Site Provisioning Workflow tool to keep more control over when Sites can be created in a Business Intranet for example. This very simple Workflow would definitely give more confidence to IT departments to open up control from what is the current pattern of containing it to a select trusted few. There are various links around this topic that I've diigo'd.
This mindset has to change for SharePoint as a Business Platform to become anywhere near as successful as the Consumer Platforms such as Facebook, MySpace and YouTube. Business Sponsors of the SharePoint Platform get quickly caught up in the "buzz words" used such as Collaboration, Workflow, Enterprise Content Management, Business Intelligence, etc. and do not realise that without the correct governance and strategy around these things nothing will ever be successful!

The mess that is inevitable when letting lose an entire company with a tool such as SPD to create and maintain workflows is a scary thought to any IT department. Their fully resourced SharePoint development team that are currently working on a high priority project might as well down tools to support the Business who have suddenly found SPD in their Start Menu and had no training, but decide to run their business processes through it for a couple of weeks and before they know it are pushing their knowledge to their limits and start leaning on IT.

I've re-read a lot of my posts and also the posts of my fellow "Perthonian", non-Metro sexual, colleague Paul Culmsee and we do keep mentioning this word Governance a lot and all that it entails! Microsoft have also kicked off with a few great posts of late and are slowly realising that unless they get a hold on the situation out and help the companies they've sold all these licenses too, SharePoint will soon become a pain in their side and lets face it Microsoft have backed it to the hilt with their product line up as their central hub.
It's one thing to sell a product to an organisation, but I also think it is the responsibility of the vendor/partner to ensure that they are guided in their use of it. This isn't just a gripe at Microsoft either, I've seen this throughout my career with the likes of Interwoven, OpenText, Documentum, BEA etc.

The company I'm currently working for are looking at using its document Business Processes in ARIS to drive how the Intranet Information Architecture is delivered. I've been doing some research and was already aware of two big Partner players in the SharePoint 2007 marketplace: Nintex and K2.

My main concerns with this are how easy it is to develop, but more importantly to maintain and whether it scales. Over the next series of posts I will be accounting my findings and trying to structure this in a way that will be useful for others who find themselves in this situation.

Published: 5/18/2008  4:50 AM | 2  Comments | 0  Links to this post

Oct 062006

Error: Changing a workflow and getting a state on a persisted Workflow Instance

I was experimenting with Persistance and created some workflow instances and unloaded them. these appeared in my database with appropriate Guid's. I then closed the application and reopened it and returned the State of the workflow fine using:

    StateMachineWorkflowInstance stateMachineWorkflowInstance = new StateMachineWorkflowInstance(workflowRuntime, instanceId);
    state = stateMachineWorkflowInstance.CurrentState.Name;


I closed the application again and then modified the workflow in the designer adding a new state and putting it between the two existing states using SetState activities.
When I compiled and ran the application again and tried to return the State I got the following error:

Index was outside the bounds of the array.
System.Runtime.Serialization.SerializationException was unhandled
  Message="The object with ID 28 implements the IObjectReference interface for which all dependencies cannot be resolved. The likely cause is two instances of IObjectReference that have a mutual dependency on each other."
  Source="mscorlib"
  StackTrace:
       at System.Runtime.Serialization.ObjectManager.GetCompletionInfo(FixupHolder fixup, ObjectHolder& holder, Object& member, Boolean bThrowIfMissing)
       at System.Runtime.Serialization.ObjectManager.CompleteObject(ObjectHolder holder, Boolean bObjectFullyComplete)
       at System.Runtime.Serialization.ObjectManager.DoFixups()
       at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
       at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
       at System.Workflow.ComponentModel.Activity.Load(Stream stream, Activity outerActivity, IFormatter formatter)
       at System.Workflow.ComponentModel.Activity.Load(Stream stream, Activity outerActivity)
       at System.Workflow.Runtime.Hosting.WorkflowPersistenceService.RestoreFromDefaultSerializedForm(Byte[] activityBytes, Activity outerActivity)
       at System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService.LoadWorkflowInstanceState(Guid id)
       at System.Workflow.Runtime.WorkflowRuntime.InitializeExecutor(Guid instanceId, CreationContext context, WorkflowExecutor executor, WorkflowInstance workflowInstance)
       at System.Workflow.Runtime.WorkflowRuntime.Load(Guid key, CreationContext context, WorkflowInstance workflowInstance)
       at System.Workflow.Runtime.WorkflowRuntime.GetWorkflow(Guid instanceId)
       at System.Workflow.Activities.StateMachineWorkflowInstance..ctor(WorkflowRuntime runtime, Guid instanceId)
       at TestApp.WorkFlowEngine.GetState(WorkflowRuntime workflowRuntime, Guid instanceId, String& state) in C:\temp\Technologies\Tracking\SimpleTrackingSample\CS\TestApp\WorkFlowEngine.cs:line 42
       at TestApp.Form1.GetState() in C:\temp\Technologies\Tracking\SimpleTrackingSample\CS\TestApp\Form1.cs:line 122
       at TestApp.Form1.btnLoadWorkflow_Click(Object sender, EventArgs e) in C:\temp\Technologies\Tracking\SimpleTrackingSample\CS\TestApp\Form1.cs:line 81
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at TestApp.Program.Main() in C:\temp\Technologies\Tracking\SimpleTrackingSample\CS\TestApp\Program.cs:line 18
       at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()


Inspecting the database and looking at the Workflow table showed that there was only one row in there with the WorkflowDefinition column being:

<ns0:Workflow1 InitialStateName="Workflow1InitialState" x:Name="Workflow1" DynamicUpdateCondition="{x:Null}" CompletedStateName="{x:Null}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ns0="clr-namespace:Microsoft.Samples.Workflow.SimpleTrackingSample;Assembly=SimpleTrackingSample, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null" />


Obviously it isn't seeing the change made as a different version and existing instances must just reference this Workflow.

What is the procedure for changing a workflow and allowing existing instances to still be loaded from persisted state?

Also, is there a way that the existing instances could take on the changes to the workflow. Obviously this gets extremely compilcated in the fact that if you remove a state from a diagram and the instance is in that state decisions will have to be made on what state it should be in.

I've posted this on the MSDN forums and hopefully someone will point me in the right direction. 

UPDATE 

"If you change the definition of a workflow and recompile it you need to change the assembly version.  The existing instances (unloaded or in memory) need the original version of the type/assembly in order to be deserialized correctly.  If you need to change the definition of an "in-flight" running instance you'll need to use the dynamic update functionality.

Thanks,
Joel West
MSFTE - SDE in WF runtime and hosting"

 Guess I'll need to look into dynamically updating the workflow on the fly and seeing how it handles this.

A few forum posts here: 1 2  

 

Published: 10/6/2006  12:00 AM | 46  Comments | 1  Links to this post

Oct 052006

WF DelayActivity State Information

I've been investigating the Windows Workflow Platform for the last two weeks and have really been pushing it to it's limits with regards to custom State Workflows and persisting it to the database. Great introduction article on State Machines in Windows Workflow and this one on the Base Activity's and this on switching on SQL Persistance.

We've been looking into the migration of existing instances from a custom made .Net workflow engine into a new M$ WF runtime instance and persisting this off to SQL 2005 database.

One issue with the migration is when you set the state where there is a Delay Activity, the instance would have alraedy been in this state for a particular time and the TimeoutDuration will have be reduced. Using the InitializeTimeoutDuration Handler on the DelayActivity in the Workflow you can write some custom code that will be fired that can adjust the TimeoutDuration when it enters that Activity.

        private void delayActivity1_InitializeTimeoutDuration(object sender, EventArgs e)
        {
            (sender as DelayActivity).TimeoutDuration = new TimeSpan(0, 1, 0);
        }

 One other issue that I am yet to resolve is if you wish to query the instance and see how long there is left on the TimeoutDuration. This function must be there but not quite sure where to find it. I've used the SqlTrackingWorkflowInstance and can't see any public properties that are relevant to this.

I've posted something in the MSDN forums hoping for a reply. 

UPDATE

Okay, so the way to get the information is as follows:

StringBuilder strReturn = new StringBuilder();

            IEnumerable<SqlPersistenceWorkflowInstanceDescription> foo = servState.GetAllWorkflows();
            foreach (SqlPersistenceWorkflowInstanceDescription s in foo)
            {
                strReturn.AppendFormat("\r\n====================================================================");
                strReturn.AppendFormat("\r\nNextTimerExpiration: {0}", s.NextTimerExpiration.ToString());
                strReturn.AppendFormat("\r\nStatus: {0}", s.Status.ToString());
                strReturn.AppendFormat("\r\nSuspendOrTerminateDescription: {0}", s.SuspendOrTerminateDescription);
                strReturn.AppendFormat("\r\nIsBlocked: {0}", s.IsBlocked.ToString());
                strReturn.AppendFormat("\r\nWorkflowInstanceId: {0}", s.WorkflowInstanceId.ToString());
            }

            return strReturn.ToString();

 The only danger of this is that if you have 250,000 workflow instances in your runtime, this will cause a performance hit...still investigating whether you can simply call for the SqlPersistenceWorkflowInstanceDescription on a given WorkflowInstanceId. The other problem is that it appears only to show the Next Timer Expiration as apposed to all the timers currently on that WorkflowInstanceId...which is possible with parallel states etc.

Waiting for a reply...
 

Published: 10/5/2006  12:00 AM | 0  Comments | 0  Links to this post