Our client recently decided to upgrade from SharePoint 2007 to 2010.
I was tasked with determining what modifications, if any, would need to be made to our custom site template.
This is the story of my trials and travails in doing so…
To keep things simple, I’ll refer to the site template as DutyCalendar.
In essence, the solution is a template for a site with two lists: ‘Duty Types’ and ‘Staff Schedule.’ The former is a list of possible work assignments, and the latter is the actual calendar. In addition, the, ‘Duty Types’ list has an associated content type (‘Duty Type’).
The code behind this is written in C# and is primarily concerned with preventing employees from being scheduled for two tasks at the same time.
Upon migration of the existing sites on my developer VM, I noticed two issues. First, when creating or modifying a calendar entry, I noticed that there were duplicate content type fields.
Issue #2, however, did not become evident until after I performed the SP2010 Visual Upgrade and was actually quite baffling.
After digging around in the code, I discovered that the content type is created by a feature the following feature receiver: SiteCollectionConfigEnsurer. When this feature receives a FeatureActivated event it executes the following code:
try { site.Features.Add(Constants.Features.ContentTypes.FEATURE_ID); } catch (System.Data.DuplicateNameException ) { /* This indicates the feature has already been activated; carry on, nothing to see here */ }Thus, Issue #1 was easily solved by commenting out these lines and re-deploying prior to migration, and then uncommenting them and re-deploying after migration.
Now, back to the real problem, Issue #2.
After a recurring calendar event is created, the expectation is that there would be two or more instances of the same event displayed by the calendar. For example, if you created an event for Monday from 10 a.m. to 11 a.m. that repeated once a week for two weeks, your calendar would show two separate events, each starting at 10 a.m. and ending at 11 a.m.
What I experienced however, was one calendar entry that started at 10 a.m. on Monday and went (notstop) until 11 a.m. on the following Monday!
There are quite a few interesting things to note here:
- Switching from preview visual upgrade back to SP2007 fixes the display!
- Switching the default view to a list view and then back to the calendar view permanently fixes the display (as documented here).
- Stepping through the code on both servers shows the same exact chain of events (i.e. multiple calendar entries are created).
- Looking at the properties for the SP2010 calendar item corroborates the display (i.e. not stored as recurrence; start date is different than end date).
- Using SharePoint Manager to create a Diff of the broken view’s XML and the fixed view’s XML (using method #2) shows additional fields have been inserted!
Here is the XML from before and after the fix…
Before:
<View Name="{70FD3928-AEDA-411E-9705-3CB027AA1F5F}" DefaultView="TRUE" Type="CALENDAR" DisplayName="Master Calendar"
Url="/sites/katie/test-one/Lists/ProfessionalStaffSchedule/Master Calendar.aspx" Level="1" BaseViewID="1" ContentTypeID="0x" ImageUrl="/_layouts/images/events.png">>
After:
<View Name="{70FD3928-AEDA-411E-9705-3CB027AA1F5F}" DefaultView="TRUE" Type="CALENDAR" Scope="Recursive" RecurrenceRowset="TRUE" DisplayName="Master Calendar"
Url="/sites/katie/test-one/Lists/ProfessionalStaffSchedule/Master Calendar.aspx" Level="1" BaseViewID="1" ContentTypeID="0x" ImageUrl="/_layouts/images/events.png">>
The good news is, as you can see, SharePoint has inserted the two highlighted items, so it should be a simple matter of creating the view with these properties set.
The bad news was that the SPView Class does not allow you to do so, as seen here (from MSDN):
public bool RecurrenceRowset { get; }
So I finally broke down and submitted this to Microsoft.
After many false starts and quite a few shared sessions, they were at last able to deliver the following workaround (click to see full-size):
Grab the code below and add it right after the view has been created (via the Update method) :
using (var webPartManager = viewMasterCalendar.ParentList.ParentWeb.GetLimitedWebPartManager(viewMasterCalendar.Url, PersonalizationScope.Shared))
{
foreach (Microsoft.SharePoint.WebPartPages.WebPart webPart in webPartManager.WebParts)
{
if (webPart is IListWebPart)
{
var listWebPart = (IListWebPart)webPart;
if ((listWebPart.ViewFlags | SPViewFlags.RecurrenceRowset) != SPViewFlags.RecurrenceRowset)
{
listWebPart.ViewFlags = listWebPart.ViewFlags | SPViewFlags.RecurrenceRowset;
webPartManager.SaveChanges(webPart);
}
}
}
}
As you can see, the RecurrenceRowSet flag is set and all is once again right with our calendar. Thank you, Microsoft!