Recently I was asked to modify a custom solution downloaded from CodePlex to allow it to updated web.config file programmatically. The deployment steps provided from CodePlex involve manual modification to web.config files on all WFE servers across the farm which is not a best practice approach for deploying custom solutions.

There are many other articles and posts discussing the same topic, however many people had the same issue that I was facing;

- It adds multiple entries into web.config file where it should only add one single entry.

- It does not delete entries from web.config file.

I’d just want to share my complete code for people who would like to get more idea on how this is done in SharePoint.

The requirement was to add the following line into <configuration><system.web><compilation><assemblies> section of web.config file.

<add assembly="MyLinksMenu, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abcdefg1234567890" />

I implemented the code inside a web application scoped feature’s event receiver class. This allows
SharePoint to add/remove the required line in web.config whenever the feature is activated/deactivated on a web application.

Here I added some class variables and an additional method.

string modPath = "configuration/system.web/compilation/assemblies";
string modOwner = "MyLinksMenu";
string modName = "add[@assembly=\"MyLinksMenu, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abcdefg123456789\"]";
string modValue = "<add assembly=\"MyLinksMenu, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abcdefg123456789\" />";

protected SPWebConfigModification createWebConfigModification()
{
  SPWebConfigModification myModification = new SPWebConfigModification(modName, modPath);
  myModification.Sequence = 0;
  myModification.Owner = modOwner;
  myModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
  myModification.Value = modValue;
  return myModification;
}

FeatureActivated Method

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
  SPWebApplication webapp = (SPWebApplication)properties.Feature.Parent;
  Collection<SPWebConfigModification> modsCollection =   webapp.WebConfigModifications;
  bool configExist = false;
  for (int i = 0; i < modsCollection.Count; i++)
  {
    if (modsCollection[i].Owner == modOwner)
    {
      configExist = true;
      break;
    }
  }
  if (!configExist)
  {
    webapp.WebConfigModifications.Add(createWebConfigModification());
    webapp.Update();
    webapp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
  }
}

FeatureDeactivating Method

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
  SPWebApplication webapp = (SPWebApplication)properties.Feature.Parent;
  Collection<SPWebConfigModification> modsCollection = webapp.WebConfigModifications;
  Collection<SPWebConfigModification> modsToBeRemoved = new Collection<SPWebConfigModification>();

  for (int i = 0; i < modsCollection.Count; i++)
  {
    if (modsCollection[i].Owner == modOwner)
    {
      modsToBeRemoved.Add(modsCollection[i]);
    }
  }

  if (modsToBeRemoved.Count > 0)
  {
    for (int i = 0; i < modsToBeRemoved.Count; i++)
    {
      webapp.WebConfigModifications.Remove(modsToBeRemoved[i]);
    }
    webapp.Update();
    webapp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
  }
}

References

How to: Add and Remove Web.config Settings Programmatically
http://msdn.microsoft.com/en-us/library/bb861909.aspx