Here is a complicated one I have been banging my head against for months.
I have a SharePoint 2010 site feature with a custom navigation provider. I have created a feature receiver that will add the navigation provider to the web.config:
[Guid("a2ecd7e8-8eac-401e-a9c8-e635e93da58a")]
public class MySiteEventReceiver : SPFeatureReceiver {
private const string WebConfigModificationOwner = "MyCustomUniqueString";
private readonly static SPWebConfigModification[] Modifications = {
// Modification for the custom site map provider
new SPWebConfigModification {
Path = "/configuration/system.web/siteMap/providers",
Name = "add[@name='CustomNavigationProvider']",
Owner = WebConfigModificationOwner,
Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode,
Value = "<add name='CustomNavigationProvider' type='" + typeof(NavigationProvider).AssemblyQualifiedName + "' NavigationType='Global' />"
},
// I have a small handful of other web.config modifications here that are not causing me any problems
};
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
try {
SPWebApplication webApp = ( (SPSite)properties.Feature.Parent ).WebApplication;
Collection<SPWebConfigModification> webConfigModifications = webApp.WebConfigModifications;
foreach ( SPWebConfigModification modification in Modifications ) {
if ( !webConfigModifications.Contains(modification) ) {
webConfigModifications.Add(modification);
}
}
webApp.Update();
webApp.WebService.ApplyWebConfigModifications();
}
catch { }
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
try {
SPWebApplication webApp = ( (SPSite)properties.Feature.Parent ).WebApplication;
Collection<SPWebConfigModification> webConfigModifications = webApp.WebConfigModifications;
for ( int i = webConfigModifications.Count - 1; i >= 0; i-- ) {
if ( webConfigModifications[i].Owner.Equals(WebConfigModificationOwner) ) {
webConfigModifications.RemoveAt(i);
}
}
webApp.Update();
webApp.WebService.ApplyWebConfigModifications();
}
catch { }
}
}
Everything is working perfectly.
A few releases later, we decided to go ahead & clean up a lot of our code. The assembly & namespaces for the custom navigation provider & feature receiver changed. We removed the old feature & deployed the new one with the new namespaces.
I never hard coded the assembly name or namespace into the feature receiver. I always used the typeof(NavigationProvider)
like the code above. I expected no problems with this migration.
To my surprise, when the feature is activated, the old namespace was added to the web.config, & the site would not work. When I manually fix the web.config to use the new namespace, all is well. But as soon as i redeploy the feature, the new namespace is replaced with the old namespace, & the site breaks again.
In an effort to debug, I have removed the above feature receiver entirely. I now have no feature receivers or any other code that edits the web.config. The web.config still gets modified with the old namespace every time I deploy, just as if the old feature receiver was still in place.
I have checked the GAC. Only the new assembly is present; the old assembly is nowhere to be found.
What could possibly be going on? Where could this old code be? Was there something horribly wrong with my feature receiver code? Is there anyway to track what assembly or feature is writing to the web.config?