Sunday, December 28, 2008

Re-Provisioning Data in a SharePoint List

Synopsis: This post addresses a technique I recently found to provision data in a SharePoint list instance where a feature may be activated and deactivated.

The documentation here tells you how you can use the ListInstance element to provision an instance of a list and you can provision that list instance with rows of data.  Here's a simplified version of ListInstance XML I've used in a file:

<ListInstance
    Description="Contains all work locations."
    Id="Location"
    OnQuickLaunch="FALSE"
    TemplateType="10012"
    Title="Location"
    Url="Lists/Location">
    <Data>
        <Rows>
            <Row>
                <Field Name="Title">Jacksonville</Field>
            </Row>
            <Row>
                <Field Name="Title">Louisville</Field>
            </Row>
            <Row>
                <Field Name="Title">Marion</Field>
            </Row>
        </Rows>
    </Data>
</ListInstance>

What the documentation lacks is any explanation of what you can put in the Field attributes.  It's pretty intuitive that the Name attribute corresponds to the name of a field. It would have been nice if the documentation explained that this was the internal name, but that's ok.  Now we know, right?  Anyway, you can just specify any field available in your list structure.  Now, if we provision our feature the data will be provisioned to the designated list.  In the example above, I had created my own list (#10012), but this could be any out-of-the-box list or document library.

That's all good, but what happens if someone deactivates and re-activates the feature.  A very likely scenario.  In that case, data is duplicated each time.  The first time the feature is activated on an empty list the follow are created:

  • Jacksonville
  • Louisville
  • Marion

When the feature is deactivated and re-activated, the list instance provisioning process occurs again and the data is duplicated.  You end up with the following:

  • Jacksonville
  • Louisville
  • Marion
  • Jacksonville
  • Louisville
  • Marion

This was certainly not desirable behavior and was confusing to me why SharePoint would do this by default.  So my options had been to programmatically delete the list or empty the list during deactivation.  Not pretty in my opinion, but it got the job done.

I lived with this "problem" for many months until I got fed up and went on a hunt for the solution.  I spent time looking for a flag somewhere that would change this default behavior.  I looked for the longest time for a way to turn this off.  What I finally figured out is that by simply specifying the ID, I can control this.  The ID field is usually automatically generated for each item in the list.  Here we're able to set the value.  All I needed to do was to specify a unique value for the ID field for each row.  That's it!  So my resulting XML looked like this:

<ListInstance
    Description="Contains all work locations."
    Id="Location"
    OnQuickLaunch="FALSE"
    TemplateType="10012"
    Title="Location"
    Url="Lists/Location">
    <Data>
        <Rows>
            <Row>
                <Field Name="ID">1</Field>
                <Field Name="Title">Jacksonville</Field>
            </Row>
            <Row>
                <Field Name="ID">2</Field>
                <Field Name="Title">Louisville</Field>
            </Row>
            <Row>
                <Field Name="ID">3</Field>
                <Field Name="Title">Marion</Field>
            </Row>
        </Rows>
    </Data>
</ListInstance>

Now, when re-provisioning the list instance data, the three items I originally provisioned will never be duplicated like before.  I can deactivate/activate the feature to my heart's content.  This is helpful for simple lookup lists like states/provinces.