代码改变世界

MOSS 2013研究系列---动态修改WebConfig(上)

2013-05-09 11:29  温森特  阅读(1565)  评论(4编辑  收藏  举报

  在开发和部署MOSS应用的时候,我们时常需要定义一些配置信息,这些信息需要部署到对应网站的虚拟目录里面的Web.Config文件里。最简单的办法是直接手工修改,简单容易,技术含量低,稳定性高,但其也有一定的缺点,人为操作,容易出错,而且部署人需要管理权限较高,需要远程到服务器上。

  因此,我们建议采用代码直接动态修改,将修改的操作放置于Feature激活事件里面,这样,当功能部署到MOSS应用的时候,激活功能Feature的时候,动态的将需要的配置信息写入到Web.Config里面,收回功能的时候,将配置信息自动移除掉,符合软件设计思想。

  闲话少说,言归正传,网上流行的方法是采用SPWebConfigModification对象进行修改,如下代码:

 


 [Guid("9bac04b2-d839-4306-a0a2-9f17b17c0165")]
    public class Feature1EventReceiver : SPFeatureReceiver
    {
        private const string SPWebConfigModificationOwner = "SPAdmin";

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            string name, xpath, value;

            SPWebApplication webApp = (SPWebApplication)properties.Feature.Parent;

            #region ..: appSettings :..
            name = "add[@key='TrustedGroup']";
            xpath = "configuration/appSettings";
            value = "<add key='TrustedGroup' value='Trusted' />";
            ModifyWebConfig(webApp, name, xpath, value, SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);

            name = "add[@key='KeyName']";
            xpath = "configuration/appSettings";
            value = "<add key='KeyName' value='Lubaochun' />";
            ModifyWebConfig(webApp, name, xpath, value, SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode);
            #endregion

            try
            {
                webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
            }
            catch (Exception ex)
            {
                RemoveAllModifications(properties);
                throw ex;
            }
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            RemoveAllModifications(properties);

            try
            {
                SPWebApplication webApp = (SPWebApplication)properties.Feature.Parent;
                webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog eventLog = new System.Diagnostics.EventLog();
                eventLog.Source = SPWebConfigModificationOwner;
                eventLog.WriteEntry(ex.Message);
                throw ex;
            }
        }

        private void RemoveAllModifications(SPFeatureReceiverProperties properties)
        {
            SPWebApplication webApp = (SPWebApplication)properties.Feature.Parent;

            List<SPWebConfigModification> modificationsToRemove = new List<SPWebConfigModification>();

            foreach (SPWebConfigModification modification in webApp.WebConfigModifications)
                if (modification.Owner == SPWebConfigModificationOwner)
                    modificationsToRemove.Add(modification);

            foreach (SPWebConfigModification modification in modificationsToRemove)
                webApp.WebConfigModifications.Remove(modification);

            webApp.Update();
        }

        private void ModifyWebConfig(SPWebApplication webApp, String nameModif, String pathModif, String valueModif, SPWebConfigModification.SPWebConfigModificationType typeModif)
        {
            SPWebConfigModification modification = new SPWebConfigModification(nameModif, pathModif);
            modification.Value = valueModif;
            modification.Sequence = 0;
            modification.Type = typeModif;
            modification.Owner = SPWebConfigModificationOwner;

            try
            {
                webApp.WebConfigModifications.Add(modification);
                webApp.Update();
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog eventLog = new System.Diagnostics.EventLog();
                eventLog.Source = SPWebConfigModificationOwner;
                eventLog.WriteEntry(ex.Message);

                throw ex;
            }
        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties) { }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties) { }
 
    }

   下图为核心方法SPWebConfigModification的调用原理图:

  经过部署测试,发现没有问题,可以动态修改Web.config里面的配置信息,但是发现它一个问题,就是这段代码一旦修改,会将所有的站点集的虚拟目录都统统改掉,而且该Feature必须是在SPWebApplication范围下的,它适合于对整体服务器场进行统一修改。

  但是,我们往往不想让它将所有的WebApp的虚拟目录配置文件修改,只是修改该Feature所属的网站集所对应的虚拟目录配置文件,这样我们需要对代码进行升级,下一个章节将对其进行详细的说明和代码示范。