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
Oct 302006

Visual Studio Add-Ins Every Developer Should Download Now

Saw this on MSDN, has a great list on 10 add ins. Always wondered how people format up code in their blogs...now I have the answer!

 Also downloaded Firefox 2.0, gotta love the spell checker built in to Input fields in a web page...great for blogging!
 

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

Oct 292006

37Signals: Getting Real

A very good book that is now freely available to read...you should check it out.

http://gettingreal.37signals.com/toc.php

Has some interesting theories in there.
 

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

Oct 232006

Using BeyondCompare in Visual Studio 2005 (VS2005)

 Always a handy tip:

In Visual Studio Choose "Options..." from the "Tools" menu. Expand "Source Control" in the treeview.

Click "Visual Studio Team Foundation Server" in the treeview. Click the "Configure User Tools..." button.

Click the "Add..." button. Enter ".*" in the "Extension" edit. Choose "Compare" in the "Operation" combobox.

Enter the path to BC2.exe in the "Command" edit.

Enter "%1 %2 /title1=%6 /title2=%7" in the "Arguments" edit.

 

Then Choose "Merge" in the "Operation" combobox.

Enter the path to BC2.exe in the "Command" edit.

Enter "%1 %2 /mergeoutput=%4 /title1=ThisComputer /title2=SourceControl" in the "Arguments" edit.

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

Oct 172006

Enterprise Library: Exception Handling Block

I've been looking into the Exception Handling Block which is part of the Enterprise Library January 2006. There is a good article on DevX which goes over defining Policies, using the Enterprise Library Logging Block and also Custom Handlers. This article also covers the same thing but in more detail. This MSDN article highlights a use for this with a Critical Errors Database scenario.

The diagram in the M$ help shows the method of defining policies for each layer and what should be logged where.

 

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

Oct 172006

Web Service Exception Handling

 I've been using the new Web Services Factory and am looking into the arguments behind Exception Shielding the internal workings of the Web Service when firing SoapExceptions. Found some great articles from Eric that explain how you can shield but also extract more detail on the errors that happened in the web service.

Write a custom ExceptionHandler to expose more details in SoapException
An ExceptionHandler that extract the detail information from the SoapException
Extending the reach of the custom ExceptionHandler

 I guess if you are simply writing a SOA solution, having access to further detail seems useful. In an environment where you are consuming or creating a web service thet will be consumed, shielding is a key element of the design. But even so, being able to pass back useful messages is important. Eric's third article shows how this can be done.

In the past I have used 'Wrappers' to pass messages up through layers rather than Exceptions as such. Then at each consuming higher layer, it checks the messages in the 'Wrappers' as it receives them. The 'Wrappers' also contain the results that obviously were expected by calling the method.

Found a great blog article by Keith Brown from PluralInsight with some really good comment feedback on the best approaches. Ryan Rinaldi's blog rant also has a very good comment reply with a solution.

 

 

Published: 10/17/2006  12:00 AM | 0  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