Earlier this week the solution designer in my company recently issued a challenge to all developers to find a bug in some code that he wrote. What happened was the build admins retracted his solution package from SharePoint when something went wrong and the whole application pool died.
It is speculated that the cause is one of the following:
- Something in the code
- Was it somehow related to retracting the solution from Central Admin?
- C – none of the above
- D – all of the above
I've been looking at the code today, but have not been able to find anything askew. I thought I'd put his code here and get an opinion from anyone who is interested in giving one. This is not a serious question and the challenge was issued in good sport, so please just give it any attention if you feel so inclined.
The message from the SD:
As I mentioned in DevDays yesterday, when the SharePoint admins retracted the CityDepartments solution package from SharePoint, the whole IIS Application Pool died. This was before the OWSTIMER.EXE timer job could unlock all the Web Applications and sites that it locked before the actual features were deactivated.
So, since nobody knows what went wrong, I will reward the first person who figures it out (myself included).
As promised, if you can find the problem in one of the FeatureDeactivating events that causes SharePoint to crash spectacularly, like it did last week, then I will buy you 2 movie tickets to any NuMetro or SterKinekor movie that is showing at the moment. The proof will be in the successful deploy and retract (3 times just to be sure) of the fixed solution package(s) in the DEV and QA environments.
List Feature Event Receiver:
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Taxonomy;
using Microsoft.Office.DocumentManagement.MetadataNavigation;
using Microsoft.Office.Server.SocialData;
namespace CityDepartmentStructure.SharepointExtractTimerJob.Features.CityDepartmentsListFeature
{
/// <summary>
/// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
/// </summary>
/// <remarks>
/// The GUID attached to this class may be used during packaging and should not be modified.
/// </remarks>
[Guid("ce0a04a0-b20b-4587-998a-6817dce2d4d8")]
public class CityDepartmentsListFeatureEventReceiver : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
try
{
SPServiceContext context = SPServiceContext.GetContext(SPServiceApplicationProxyGroup.Default, SPSiteSubscriptionIdentifier.Default);
SocialTagManager stm = new SocialTagManager(context);
TaxonomySession taxonomySession = stm.TaxonomySession;
TermStore termStore = taxonomySession.DefaultSiteCollectionTermStore;
Group termGroup = termStore.Groups["CityDepartments"];
TermSet termSet = termGroup.TermSets["Directorates"];
using (SPWeb web = properties.Feature.Parent as SPWeb)
{
web.Lists.Add("DepartmentSites", "This list maintains a list of web sites for all Org Units in CCT", SPListTemplateType.Links);
web.Update();
SPList departmentsList = web.Lists["DepartmentSites"];
TaxonomyField taxonomyField = departmentsList.Fields.CreateNewField("TaxonomyFieldType", "OrgLevel") as TaxonomyField;
taxonomyField.Description = "Org Unit in the Org Structure. Can be a Directorate, Department, Branch or Section.";
taxonomyField.SspId = termStore.Id;
taxonomyField.TermSetId = termSet.Id;
taxonomyField.AllowMultipleValues = false;
taxonomyField.CreateValuesInEditForm = false;
taxonomyField.Open = false;
taxonomyField.Group = "CCT Metadata Field Content Type";
taxonomyField.Required = true;
departmentsList.Fields.Add(taxonomyField);
TaxonomyField field = departmentsList.Fields["OrgLevel"] as TaxonomyField;
field.Title = "OrgLevel";
field.Update(true);
departmentsList.Update();
SPView view = departmentsList.DefaultView;
view.ViewFields.Add("OrgLevel");
view.Update();
var navigationField = departmentsList.Fields["OrgLevel"] as SPField;
MetadataNavigationSettings navigationSettings = MetadataNavigationSettings.GetMetadataNavigationSettings(departmentsList);
MetadataNavigationHierarchy navigationHierarchy = new MetadataNavigationHierarchy(navigationField);
navigationSettings.AddConfiguredHierarchy(navigationHierarchy);
MetadataNavigationSettings.SetMetadataNavigationSettings(departmentsList, navigationSettings, true);
departmentsList.Update();
MetadataNavigationKeyFilter navigationKeyFilter = new MetadataNavigationKeyFilter(navigationField);
navigationSettings.AddConfiguredKeyFilter(navigationKeyFilter);
MetadataNavigationSettings.SetMetadataNavigationSettings(departmentsList, navigationSettings, true);
departmentsList.Update();
}
}
catch (Exception ex)
{
throw ex;
}
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
try
{
using (SPWeb web = properties.Feature.Parent as SPWeb)
{
SPList departmentsList = web.Lists["DepartmentSites"];
departmentsList.Delete();
}
}
catch (Exception ex)
{
throw ex;
}
}
}
}
Timer Job Feature Event Receiver:
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Linq;
namespace CityDepartmentStructure.SharepointExtractTimerJob.Features.Feature1
{
/// <summary>
/// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
/// </summary>
/// <remarks>
/// The GUID attached to this class may be used during packaging and should not be modified.
/// </remarks>
[Guid("10e80e0f-7be3-46f0-8a7f-fcf806ddf762")]
public class Feature1EventReceiver : SPFeatureReceiver
{
private const string JobName = "ExtractTimerJob";
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPService service = GetService();
// Remove job if it exists.
DeleteJobAndSettings(service);
// Create the job.
ExtractTimerJob job = new ExtractTimerJob(JobName, service);
// Create the schedule so that the job runs hourly, sometime
// during the first quarter of the hour.
SPHourlySchedule schedule = new SPHourlySchedule();
schedule.BeginMinute = 0;
schedule.EndMinute = 15;
job.Schedule = schedule;
job.Update();
// Configure the job.
ExtractTimerJobSettings jobSettings = new ExtractTimerJobSettings(service, Guid.NewGuid());
jobSettings.Name = "ExtractTimerJobSettings";
jobSettings.WebServiceLocation = "http://r3pci01.capetown.gov.za:8150/sap/zget_orgstruct";
jobSettings.Update(true);
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
DeleteJobAndSettings(GetService());
}
private void DeleteJobAndSettings(SPService service)
{
// Find the job and delete it.
foreach (SPJobDefinition job in service.JobDefinitions)
{
if (job.Name == JobName)
{
job.Delete();
break;
}
}
// Delete the job's settings.
ExtractTimerJobSettings jobSettings = service.GetChild<ExtractTimerJobSettings>("ExtractTimerJobSettings");
if (jobSettings != null)
{
jobSettings.Delete();
}
}
private static SPService GetService()
{
// Get an instance of the SharePoint farm.
SPFarm farm = SPFarm.Local;
// Get an instance of the service.
var results = from s in farm.Services
where s.Name == "SPSearch4"
select s;
SPService service = results.First();
return service;
}
}
}