Working with one of my customers and they were wanting to setup an email notification on a custom site that was originally based on a blog site.  The notification needed to be sent whenever someone created/modified a post or a comment associated with the post, and the alert needed to be based on the Categories associated with the Post.  For example, there is a category named "IT" and users wanted to be notified anytime someone creates or modifies a post that has the "IT" category associated with it.  We created a simple sequential workflow to handle the logic of sending out the notifications; however, the problem came in when we modified their custom new and edit pages.  These were ASP.Net pages leveraging the SharePoint Form Field controls.  These pages originally did not display the Category field as they were not being used.  Since they wanted multiple categories for each item, we setup the out of the box Category field on the Post list to be Multi-select and then included a MultipleLookupField control to the page, and hooked up the control in the code behind, everything's working great.

We move the code and pages to the test server and they work until we hookup the workflow.  Then we get this exception:

Exception type: System.InvalidCastException
Message: Unable to cast object of type 'Microsoft.SharePoint.SPFieldWorkflowStatus' to type 'Microsoft.SharePoint.SPFieldLookup'.

That's odd, the page isn't hooking anything up to WorkflowStatus, so we unhook the workflow and the page starts loading.  Add the workflow back and the page still works.  IISReset and the page is still loading.  Thinking everything is done, we call it a night. 

Next day, we find out the exception is back.  To see what's going on I get a copy of the pages and setup a repro.  Luckily the issue reproduced on my dev box, so I attached windbg.exe [from the Debugging Tools for Windows install] to the app pool and run the following command to break on managed exceptions:

sxe clr

I then reproduce the issue and windbg breaks on the managed exception.  I ran !clrstack to confirm it's the stack from the ASPX Error page.  This confirms that SharePoint is looping through the controls on the page and hooking up the SharePoint column to the field controls that are specified, but based on the exception, when it's trying to load our MultipleLookupField control, it's trying to hook up the Workflow Status instead of the Category column:

0:020> !clrstack
OS Thread Id: 0x1450 (20)
ESP       EIP    
03f5e8a8 7793fbae [HelperMethodFrame_1OBJ: 03f5e8a8]
03f5e908 0b6b3820 Microsoft.SharePoint.WebControls.LookupField.CreateChildControls()
03f5ea18 0b6b306e Microsoft.SharePoint.WebControls.MultipleLookupField.CreateChildControls()
03f5ea3c 6d4fd2f8 System.Web.UI.Control.EnsureChildControls()
03f5ea68 0b14bfb1 Microsoft.SharePoint.WebControls.BaseFieldControl.OnLoad(System.EventArgs)
03f5ecb0 6d4fc2a3 System.Web.UI.Control.LoadRecursive()
03f5ecc8 6d4fc2fe System.Web.UI.Control.LoadRecursive()
03f5ece0 6d4fc2fe System.Web.UI.Control.LoadRecursive()
03f5ecf8 6d4fc2fe System.Web.UI.Control.LoadRecursive()
03f5ed10 6d4fc2fe System.Web.UI.Control.LoadRecursive()
03f5ed28 6d4fc2fe System.Web.UI.Control.LoadRecursive()
03f5ed40 6d4fc2fe System.Web.UI.Control.LoadRecursive()
03f5ed58 6d4f8354 System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean)
03f5eeb0 6d4f7f84 System.Web.UI.Page.ProcessRequest(Boolean, Boolean)
03f5eee8 6d4f7eb1 System.Web.UI.Page.ProcessRequest()
03f5ef20 6d4f7e46 System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext)
03f5ef2c 6d4f7e22 System.Web.UI.Page.ProcessRequest(System.Web.HttpContext)

 

From here I took a look at the objects on the stack to try and figure out why SharePoint is linking the MultipleLookupColumn to Workflow Status.  You do this by running !dumpstackobjects [!dso] on the thread that has the exception on it.  This will dump out a list of objects associated with the stack:

0:020> !dso
OS Thread Id: 0x1450 (20)
ESP/REG  Object   Name
03f5e7d8 0251439c System.InvalidCastException
03f5e820 0251439c System.InvalidCastException
03f5e868 024a4dac Microsoft.SharePoint.WebControls.MultipleLookupField
---
03f5e948 024db9cc Microsoft.SharePoint.SPFieldCollection 
---

I can see the SPFieldCollection object which is the XML Schema of the fields associated with the list, so I dump this out using !dumpobject [!do]. 

0:020> !do 024db9cc
Name: Microsoft.SharePoint.SPFieldCollection
MethodTable: 03f0e3ac
EEClass: 077f49e0
Size: 84(0x54) bytes
GC Generation: 0
 (C:\Windows\assembly\GAC_MSIL\Microsoft.SharePoint\12.0.0.0__71e9bce111e9429c\Microsoft.SharePoint.dll)
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
07922af0  40010be        4 ...SPPersistedObject  0 instance 00000000 m_ContainingObject
71a72da0  400007a       10         System.Int32  1 instance        0 m_cDirtyUpdates
0969d670  400007b        8 ...rtyUpdateDelegate  0 instance 00000000 OnAddDelayDirtyUpdate
0969d754  400007c        c ...rtyUpdateDelegate  0 instance 00000000 OnRemoveDelayDirtyUpdate
71a72da0  400007d       14         System.Int32  1 instance       -1 m_potentialErrorIndex
096b832c  40027b4       18 ...SharePoint.SPList  0 instance 00000000 m_List
07b1dcd4  40027b5       1c ....SharePoint.SPWeb  0 instance 02451528 m_web
71a44620  40027b6       4c       System.Boolean  1 instance        1 m_bAll
71a72da0  40027b7       48         System.Int32  1 instance        6 m_iCount
00000000  40027b8       20                ARRAY  0 instance 024dba20 m_arrFieldSchema
71a44620  40027b9       4d       System.Boolean  1 instance        1 m_arrFieldSchemaInited
71a44324  40027ba       24      System.Object[]  0 instance 024dbce0 m_arrFieldSchemaFull
71a44620  40027bb       4e       System.Boolean  1 instance        1 m_arrFieldSchemaFullInited
71a70b54  40027bc       28        System.String  0 instance 024da8cc m_strExtendedFieldsXml
71a731a8  40027bd       2c ...ections.Hashtable  0 instance 024e2c38 m_htIdx2Fld
71a731a8  40027be       30 ...ections.Hashtable  0 instance 024e615c m_InternalNameDict
71a731a8  40027bf       34 ...ections.Hashtable  0 instance 024e626c m_InternalNameWithPrefixDict
71a731a8  40027c0       38 ...ections.Hashtable  0 instance 024ee088 m_DisplayNameDict
71a731a8  40027c1       3c ...ections.Hashtable  0 instance 00000000 m_IdDict
71a70b54  40027c2       40        System.String  0 instance 00000000 m_strScope
00000000  40027c3       44                       0 instance 00000000 m_Scopes
00000000  40027c4      b80                       0   shared   static s_SPFieldCreatorDelegates
    >> Domain:Value  01236970:NotInit  01739ae0:01b81e2c <<
71a6a35c  40027c5      b84 ....ReaderWriterLock  0   shared   static s_fieldMutex
    >> Domain:Value  01236970:NotInit  01739ae0:01b81e54 <<

From here, the  m_strExtendedFieldsXml property contains the data we're after, so we dump this out.  You could also dump out the other Schema properties to get one field at a time, but this property will dump out all the Schema as one string so it's easier to get:

0:020> !do 024da8cc
Name: System.String
MethodTable: 71a70b54
EEClass: 7182d65c
Size: 4352(0x1100) bytes
GC Generation: 0
 (C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: <Fields><Field ID="{c042a256-787d-4a6f-8a8a-cf6ab767f12d}" ...<
Field></Fields> 
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
71a72da0  4000096        4         System.Int32  1 instance     2168 m_arrayLength
71a72da0  4000097        8         System.Int32  1 instance     2167 m_stringLength
71a71834  4000098        c          System.Char  1 instance       3c m_firstChar
71a70b54  4000099       10        System.String  0   shared   static Empty
    >> Domain:Value  01236970:01ac1198 01739ae0:01ac1198 <<
71a71784  400009a       14        System.Char[]  0   shared   static WhitespaceChars
    >> Domain:Value  01236970:01ac16f0 01739ae0:01ac6508 <<

The highlighed String property above contains all the XML schema that defines all the fields associated with the list.  I truncated the above view as it was 5-10 lines long on the page.  I then copied out the XML from the String property, create a new XML document in SharePoint Designer 2007 and paste in the info from the dump.  I can then right-click the page and select "Reformat XML" to clean up what I'm looking at.  I then search for the text "Category" and find the problem.  When the workflow was hooked up, the Workflow Status field has a StaticName and Name value of "Category".  I then find the field with a DisplayName of Category that we're trying to hook up to, and find it has a static name of "PostCategory".  

Workflow Status field that our control is picking up (some properties removed to keep the lines short):
 <Field DisplayName="CategoryAlert" Type="WorkflowStatus" ... StaticName="Category" Name="Category" ... >

Category field that we're trying to hookup (some properties removed to keep the lines short):
 <Field DisplayName="Category" Type="LookupMulti" ... StaticName="PostCategory" Name="PostCategory" ... />


SharePoint will pick up either the Display or Static name of a column, and in this case it was hitting the Workflow Status field first when enumerating controls and picking up the StaticName property before it was picking up the field with a DisplayName of Category.  We update our MultipleLookupField to point to the static name of our column to ensure there are no questions about which field we want, PostCategory, instead of the display name of Category and everything is happy.  Here's what the change looked like:

From:    <SharePoint:MultipleLookupField runat="server" ID="mlfCategory" ControlMode="New" FieldName="Category">

To:   <SharePoint:MultipleLookupField runat="server" ID="mlfCategory" ControlMode="New" FieldName="PostCategory">

You can get the Static and Display Name for fields from teh browser:

  1. Browse the list
  2. Click Settings, then List Settings
  3. Click a Column

The Display Name will show as the Column Name
The Static Name will display in the URL QueryString after Field =