Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I've written a feature assembly that includes an SPFeatureReceiver. I can successfully deploy the feature's WSP, the assembly goes to the GAC, and the feature (mostly) does what it's supposed to. However, when I edit the settings here for both the application and web frontend servers in the farm:

c:\inetpub\wwwroot\wss\VirtualDirectories\443\web.config

And add this to configuration/configSections:

<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
  <section name="MyAssembly.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=xxx" requirePermission="false" />
</sectionGroup>

And add this to configuration:

<applicationSettings>
  <MyAssembly.Properties.Settings>
    <setting> ...
    </setting>
  </MyAssembly.Properties.Settings>
</applicationSettings>

Those settings are ignored, and the System.Configuration.DefaultSettingValueAttribute values are being used instead. So. Where is this assembly looking for its settings?


Edit

As it turns out, it was trying to load from here: C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.config, and sometimes C:\inetpub\wwwroot\wss\VirtualDirectories\30482\web.config (neither of which are the correct SharePoint folders).

share|improve this question
add comment

3 Answers

You will probably find that changing web.config files to store application settings for SharePoint Features is not your best solution.

For an alternate solution that may work better for you, please refer to the Applications Setting Manager of the Microsoft Patterns and Practice SharePoint Guidance.

SharePoint 2007 guidance includes a section on Managing Application Configuration that discuses web.config changes through APIs. However, in practice, those have proven less reliable than the updated guidance which stores properties in the configuration database.

share|improve this answer
    
+1 This is how it should be done. –  Anders Rask Jan 7 '13 at 7:52
add comment

You need to work with SPWebConfigModification class to perform web configuration (web.config) changes across SharePoint farm.

class WebConfigReceiver : SPFeatureReceiver
{
        private const string MyOwner = "OwnerName";

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

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

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

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

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

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            RemoveWebEntries(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 = MyOwner;
                eventLog.WriteEntry(ex.Message);
                throw ex;
            }
        }

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

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

            foreach (SPWebConfigModification modification in webApp.WebConfigModifications)
                if (modification.Owner == MyOwner)
                    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 = MyOwner;

            try
            {
                webApp.WebConfigModifications.Add(modification);
                webApp.Update();
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }


    }

However, to store the custom configurations, I would strongly recommend you to use Web application, Farm or Web level property bags instead.

share|improve this answer
    
This is a good start, but I use applicationSettings instead of appSettings. So correct me if I'm wrong - my Path would be: configuration/applicationSettings/MyAssembly.Properties.Settings, and my Value would be: <setting name="xxx" serializeAs="String"> <value>...</value> </setting> –  Reinderien Jan 3 '13 at 15:00
    
The basic <appSettings>is easier to deal with - just slap in a <add key="...." value="..." /> entry and you're done. –  Falak Mahmood Jan 3 '13 at 22:24
    
You just access it as ConfigurationManager["(key)"] and then it's up to you to know what you're dealing with. –  Falak Mahmood Jan 3 '13 at 22:25
    
Falak, I've experienced issues related to removing changes through SPWebConfigModification like some explained here blogs.devhorizon.com/reza/2008/01/05/… Have you ever seen issues like Reza describes? And how do you deal with them? Thanks,Tom –  Tom Resing Jan 4 '13 at 15:32
1  
Please refrain from excessive commenting on posts. Instead use our chat for discussions please! –  Anders Rask Jan 7 '13 at 7:51
show 7 more comments
up vote -3 down vote accepted

Property bags and SharePoint content database usage might be the best way to go, if it weren't for the fact that I need to also store settings that tell the application how to connect to SharePoint in the first place.

I ended up writing a simple module that saves everything to one explicitly specified .config, using the System.Configuration namespace, and writing custom ConfigurationSection classes. Now I can be guaranteed to know where the settings are being stored; I don't need any SharePoint dependencies to do settings (just .NET itself); and I don't need to add any third-party software (such as PBM) to be able to edit the settings outside of the application.

share|improve this answer
1  
Use the SPFeatureReceiverProperties to connect to SharePoint. –  Tom Resing Jan 6 '13 at 19:43
    
I agree with Tom or use property bags approach. –  Falak Mahmood Jan 7 '13 at 3:30
    
This is not a recommended approach for storing settings in SharePoint. Use Hierarchical Configuration Manager as Tom mentions in his answer –  Anders Rask Jan 7 '13 at 7:53
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.