I have read about best Practices for development once it comes to SPWebConfigModification and write feature to read xml file and modify web.config files and works fine on my local environment but once we try to deploy on test environment with multiple WFE and status keep saying Deploying and also once we try to enable webapplication level feature to modify web.config file its say "A web configuration modification operation is already running." I would like to take look at code and please advise if something wrong in my code. please find code below
public override void FeatureActivated(SPFeatureReceiverProperties properties) {
//this.FeatureActivated(properties);
this.ReadDeploymentSettings(properties);
SPWebApplication webApplication = properties.Feature.Parent as SPWebApplication;
Installer installer = new Installer() {
WebApplicationId = webApplication.Id,
Nodes = this.DeploymentNodes,
DllsToGac = this.DllsToGac
};
installer.Deploy(Installer.DeploymentType.Deploy);
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {
//this.FeatureDeactivating(properties);
//this.ReadDeploymentSettings(properties);
SPWebApplication webApplication = properties.Feature.Parent as SPWebApplication;
Installer installer = new Installer() {
WebApplicationId = webApplication.Id,
// Nodes = this.DeploymentNodes,
// DllsToGac = this.DllsToGac
};
installer.Deploy(Installer.DeploymentType.UnDeploy);
}
Installer.cs
public class Installer {
#region Enums
/// <summary>
/// Deployment type.
/// </summary>
public enum DeploymentType
{
/// <summary>
/// Deploy.
/// </summary>
Deploy,
/// <summary>
/// Undeploy.
/// </summary>
UnDeploy
}
#endregion // Enums
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Installer"/> class.
/// </summary>
public Installer()
{
}
#endregion // Constructors
#region Proeprties
/// <summary>
/// Gets or sets the web application id.
/// </summary>
/// <value>The web application id.</value>
public Guid WebApplicationId { get; set; }
/// <summary>
/// Gets or sets the nodes collection.
/// </summary>
/// <value>The nodes.</value>
public XmlNodeList Nodes { get; set; }
/// <summary>
/// Gets or sets the collection of DLLs to be installed into the GAC.
/// </summary>
/// <value><see cref="Dictionary"/> of dlls.</value>
public Dictionary<string, string> DllsToGac { get; set; }
#endregion // Proeprties
private const string _owner = "TelerikConfigFeature";
#region Methods
/// <summary>
/// Makes required changes for web.config based on deployment type.
/// </summary>
/// <param name="deploymentType">Type of the deployment.</param>
public void Deploy(DeploymentType deploymentType) {
this.ModifyWebConfig(deploymentType);
//this.ModifyGac(deploymentType);
}
/// <summary>
/// Modifies the GAC.
/// </summary>
/// <param name="deploymentType">Type of the deployment.</param>
private void ModifyGac(DeploymentType deploymentType) {
foreach (string key in this.DllsToGac.Keys) {
string assembly = this.DllsToGac[key] + key;
Publish p = new Publish();
if (deploymentType == DeploymentType.Deploy)
p.GacInstall(assembly);
else
p.GacRemove(assembly);
}
}
/// <summary>
/// Modifies the web config.
/// </summary>
/// <param name="deploymentType">Type of the deployment.</param>
private void ModifyWebConfig(DeploymentType deploymentType) {
SPWebApplication webApplication = SPWebService.ContentService.WebApplications[this.WebApplicationId];
if (deploymentType == DeploymentType.Deploy && webApplication!=null) {
Collection<SPWebConfigModification> webConfigModifications = this.CreateWebConfigModifications();
// Clears the SPWebConfigModification collection, in order to prevent appling of
// earlier entered modifications.
webApplication.WebConfigModifications.Clear();
foreach (SPWebConfigModification webConfigModification in webConfigModifications) {
webApplication.WebConfigModifications.Add(webConfigModification);
/* if (deploymentType == DeploymentType.Deploy)
webApplication.WebConfigModifications.Add(webConfigModification);
else
webApplication.WebConfigModifications.Remove(webConfigModification); */
}
}
else {
if (webApplication != null) {
Collection<SPWebConfigModification> collection = webApplication.WebConfigModifications;
int _Count = collection.Count;
// Remove any modifications that were originally created by the owner.
for(int i=_Count-1;i>=0;i--) {
SPWebConfigModification configMod = collection[i];
if (configMod.Owner == _owner)
collection.Remove(configMod);
}
}
}
// Applyes all modification to web.config.
webApplication.Update();
webApplication.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
//webApplication.WebService.ApplyWebConfigModifications();
// webApplication.Update();
}
/// <summary>
/// Creates collection of the web config modifications, based on
/// information from XML file.
/// </summary>
/// <returns><see cref="Collection"/> of <see cref="SPWebConfigModification"/></returns>
private Collection<SPWebConfigModification> CreateWebConfigModifications() {
Collection<SPWebConfigModification> webConfigModifications = new Collection<SPWebConfigModification>();
foreach (XmlNode node in this.Nodes) {
// Throws out comments.
if (node.NodeType == XmlNodeType.Comment)
continue;
SPWebConfigModification webConfigModification = new SPWebConfigModification();
webConfigModification.Name = node.Attributes["Name"].Value;
webConfigModification.Path = node.Attributes["Path"].Value;
webConfigModification.Sequence = 0;
webConfigModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
webConfigModification.Value = node.InnerXml;
webConfigModification.Owner = _owner;
webConfigModifications.Add(webConfigModification);
}
return webConfigModifications;
}
#endregion // Methods
}